ВЫБОР нескольких столбцов через подзапрос

18

Я пытаюсь выбрать 2 столбца из подзапроса в следующем запросе, но не могу это сделать. Попытался создать таблицу псевдонимов, но все еще не мог получить их.

SELECT
  DISTINCT petid,
  userid,
  (SELECT MAX(comDate) FROM comments WHERE petid=pet.id) AS lastComDate,
  (SELECT userid FROM comments WHERE petid=pet.id ORDER BY id DESC LIMIT 1) AS lastPosterID
FROM 
  pet LEFT JOIN comments ON pet.id = comments.petid
WHERE 
  userid='ABC'      AND 
  deviceID!='ABC'   AND 
  comDate>=DATE_SUB(CURRENT_TIMESTAMP, INTERVAL 2 MONTH);

По сути, я пытаюсь получить lastComDate& lastPosterIDиз той же строки - строки, которая является последней в комментариях для конкретного питомца. Пожалуйста, предложите, как я могу получить их эффективным способом.

Приведенный выше запрос работает, но кажется излишним, так как одна и та же строка выбирается дважды. Более того, ORDER BYпредложение значительно медленнее, чем агрегатная функция - как я обнаружил при профилировании запроса. Таким образом, решение, избегающее сортировки, будет оценено.

BufferStack
источник
1
Если бы у вас был индекс (petid, id) в таблице комментариев, порядок, скорее всего, был бы не медленным, а обо всем по порядку: кажется, что ваш запрос запрашивает всех домашних животных, для которых userrid 'ABC' прокомментировал их в течение последних двух месяцев, где deviceID не является «ABC» (хотя неясно, в какой таблице находится deviceID столбца, возможно домашние животные и, возможно, комментарии), кто был последним комментатором, и дата последнего комментария. Это правильно?
Майкл - sqlbot
@ Michael-sqlbot - Да, именно это я и пытаюсь собрать. Это deviceIDиз petsтаблицы - это означает, что я не получаю домашних животных, которые представлены самим «ABC».
BufferStack

Ответы:

13
SELECT DISTINCT petid, userid, lastComDate, lastPosterId
FROM 
    pet 
    LEFT JOIN comments ON pet.id = comments.petid 
    LEFT JOIN (
        SELECT MAX(comDate), userid, petid FROM comments GROUP BY userid
    ) a ON a.petid = pet.id
WHERE 
    userid='ABC' 
    AND deviceID!='ABC' 
    AND comDate>=DATE_SUB(CURRENT_TIMESTAMP, INTERVAL 2 MONTH)
;

Вы также можете вытащить свой подзапрос во временную таблицу, если производительность снизится где-нибудь в будущем.

валькирия
источник
Я пробовал это и раньше ... это возвращается NULLдля обоих lastComDateи lastPosterIdдля всех записей.
BufferStack
У вас есть образцы данных?
Валькирия
Как мне предоставить пример данных?
BufferStack
Попробуйте подсказки в этом сообщении: meta.stackexchange.com/questions/156729/…
Валькирия,
1
Это хорошо, но SQLFiddle лучше;). Смотрите пример здесь . Лучше просто увидеть код и начальные данные, а не таблицу, которую вам нужно будет отформатировать.
Marian
6

Учитывая, что ваши таблицы выглядят так:

create table pet (id int, userid int, deviceid int);
create table comments (id int, petid int, comdate date);

Этот запрос должен помочь:

SELECT 
        p.id, 
        p.userid,
        (SELECT MAX(comDate)
         FROM comments
         WHERE petid = p.id
         AND comDate >= DATE_SUB(
                 CURRENT_TIMESTAMP, INTERVAL 2 MONTH)
               ) AS lastComDate,
        (SELECT userid
         FROM comments
         WHERE petid = p.id
         AND comDate >= DATE_SUB(
              CURRENT_TIMESTAMP, INTERVAL 2 MONTH
         ) ORDER BY id DESC LIMIT 1) AS lastPosterID
    FROM 
        pet p

    WHERE 
        p.userid=1
        AND p.deviceID!=1
Друзин
источник