サブクエリを介して複数の列を選択する


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-特定のペットのコメントの最新の行です。効率的な方法でそれらを取得する方法を提案してください。

上記のクエリは機能しますが、同じ行が2回フェッチされるため、過剰に思えます。さらに、ORDER BYクエリのプロファイリング中に見つけたように、句は集計関数よりもかなり遅くなります。そのため、ソートを回避するソリューションが必要です。


1
コメントテーブルにindex(petid、id)がある場合、順序は遅くなることはまずありませんが、まず最初に:ユーザーID 'ABC'がコメントしているすべてのペットをクエリが要求しているようです過去2か月以内で、deviceIDが「ABC」ではない場合(ただし、deviceIDが列であるかどうかは不明ですが、ペットやコメントである可能性があります)、最後のコメント者は誰で、最後のコメントの日付です。そうですか?
マイケル-sqlbot

@ Michael-sqlbot-はい、それはまさに私が収集しようとしているものです。これdeviceIDpetsテーブルからのものです。つまり、「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の両方のためのlastComDatelastPosterIdすべてのレコードのを。
BufferStack

利用可能なサンプルデータはありますか?
ヴァルキリー

サンプルデータを提供するにはどうすればよいですか?
BufferStack

この記事でヒントをお試しください:meta.stackexchange.com/questions/156729/...
ヴァルキリー

1
それは良いことですが、SQLFiddleの方が優れています;)。こちらの例をご覧ください。書式設定する必要のあるテーブルではなく、コードとシードデータを表示する方が良いでしょう。
マリアン

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.