web-dev-qa-db-ja.com

サブクエリを通じて複数の列を選択する

次のクエリのサブクエリから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);

基本的に、同じ行からlastComDatelastPosterIDを取得しようとしています-特定のペットのコメントで最新の行です。どうすれば効率的に入手できるか提案してください。

上記のクエリは機能しますが、同じ行が2回フェッチされるため、やり過ぎに思われます。さらに、ORDER BY句は、集計関数よりも大幅に遅くなります-クエリのプロファイリング中に見つけたように。したがって、並べ替えを回避するソリューションがいただければ幸いです。

18
BufferStack
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)
;

パフォーマンスが将来どこかで影響を受けるようになった場合は、サブクエリを一時テーブルに引き出すこともできます。

13
Valkyrie

テーブルが次のようになっているとします。

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
6
druzin