Mehrere Spalten über eine Unterabfrage auswählen


18

Ich versuche, 2 Spalten aus der Unterabfrage in der folgenden Abfrage auszuwählen, kann dies jedoch nicht. Es wurde versucht, eine Alias-Tabelle zu erstellen, sie konnte jedoch nicht abgerufen werden.

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

Grundsätzlich versuche ich, das lastComDate& lastPosterIDaus derselben Zeile zu erhalten - der Zeile, die in den Kommentaren für das jeweilige Haustier die neueste ist. Bitte schlagen Sie vor, wie ich sie auf effiziente Weise erhalten kann.

Die obige Abfrage funktioniert, scheint jedoch zu viel zu sein, da dieselbe Zeile zweimal abgerufen wird. Darüber hinaus ist die ORDER BYKlausel erheblich langsamer als die Aggregatfunktion - wie ich bei der Profilerstellung festgestellt habe. Eine Lösung, die das Sortieren vermeidet, wäre also wünschenswert.


1
Wenn Sie einen Index (petid, id) in der Kommentartabelle hätten, wäre die Reihenfolge nach wahrscheinlich nicht langsam, aber das Wichtigste zuerst: Ihre Abfrage fragt anscheinend nach allen Haustieren, zu denen die Benutzer-ID 'ABC' einen Kommentar abgegeben hat sie innerhalb der letzten zwei Monate, in denen die Geräte-ID nicht 'ABC' ist (obwohl unklar ist, in welcher Tabelle die Geräte-ID enthalten ist, möglicherweise Haustiere und möglicherweise Kommentare) und wer der letzte Kommentator war und das Datum des letzten Kommentars. Ist das richtig?
Michael - sqlbot

@ Michael-sqlbot - Ja, genau das versuche ich zu sammeln. Das deviceIDist vom petsTisch - was bedeutet, dass ich nicht die Haustiere bekomme, die von 'ABC' selbst eingereicht wurden.
BufferStack

Antworten:


12
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)
;

Sie können Ihre Unterabfrage auch in eine temporäre Tabelle verschieben, wenn die Leistung später beeinträchtigt wird.


Ich hatte das auch schon früher versucht ... das kehrt NULLfür beide lastComDateund lastPosterIdfür alle Datensätze zurück.
BufferStack

Haben Sie Musterdaten zur Verfügung?
Walküre

Wie stelle ich die Beispieldaten bereit?
BufferStack

Versuchen Sie die Hinweise in diesem Beitrag: meta.stackexchange.com/questions/156729/…
Walküre

1
Das ist gut, aber SQLFiddle ist besser;). Sehen Sie ein Beispiel hier . Viel besser, um nur den Code und die Startdaten zu sehen, nicht irgendeine Tabelle, die Sie formatieren müssen.
Marian

6

Vorausgesetzt, Ihre Tabellen sehen folgendermaßen aus:

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

Diese Abfrage sollte den Trick machen:

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.