2012-02-04 22 views
14

Załóżmy, że mam dwie następujące tabele:LEFT JOIN na MAX wartość

STUDENT 
studentid lastname firstname 
1   Smith  John 
2   Drew  Nancy 

STUDENT_STORY 
studentid dateline storyid status 
1   1328313600 10  2 
1   1328313601 9   1 
2   1328313602 14  2 
2   1328313603 12  1 

Teraz muszę zapytanie SQL, które wybrać każdemu studentowi wraz z najnowszej historii dla tego studenta w tabeli historia studenta.

próbuję to:

SELECT s.*, ss.* 
FROM student AS s 
LEFT JOIN (
    SELECT * 
    FROM student_story 
    WHERE student_story.studentid = s.studentid 
    ORDER BY dateline DESC LIMIT 1 
) AS ss ON (ss.studentid = s.studentid) 

Jednak ta kwerenda nie działa. Narzeka, że ​​s.studentid jest nieznanym polem w klauzuli where sub-zapytania.

Proszę zasugerować, w jaki sposób mogę osiągnąć to, co próbuję zrobić.

Dzięki.

Odpowiedz

17

spróbować czegoś takiego:

SELECT 
    s.*, 
    ss.* 
FROM 
    student AS s 
LEFT JOIN 
    student_story AS ss 
ON (ss.studentid = s.studentid) 
WHERE ss.dateline = (
    SELECT 
    MAX(dateline) 
    FROM 
    student_story AS ss2 
    WHERE 
    ss2.studentid = s.studentid 
) 
+1

Teraz, kiedy o tym myślę, to może wrócić tego samego ucznia dwa razy, gdyby nie było wiele wpisów z tym samym znacznikiem czasu, więc prawdopodobnie tego nie używaj. – Detheroc

+0

Nigdy nie powinno tak być, chyba że coś jest nie tak. Jak naprawić to zapytanie, aby nie zwracał tego samego ucznia dwa razy, jeśli istnieje wiele wpisów o tym samym znaczniku czasu? – akanevsky

+0

Jeśli liczba identyfikatorów w tabeli student_story również wzrasta z czasem, możesz zamiast tego wybrać i porównać maksymalny identyfikator. Nie wydaje się, że tak jest w twoim przykładzie, więc problem jest prawdopodobnie dość skomplikowany. Czy rozwiązanie Vyktora nie działało? Wydaje się to całkiem rozsądne. – Detheroc

1

Ten dołączyć należy zrobić:

SELECT s.*, ss.* 
FROM student_story AS ss 
LEFT JOIN student AS s 
    ON student_story.studentid = s.userid 
GROUP BY ss.studentid 

GROUP BY powinien wziąć ostatni wiersz, więc ostatnia historia = ostatni wiersz, jeśli to nie zadziała spróbuj :

GROUP BY ss.studentid, ss.dateline DESC 

nie jestem pewien temat, prosimy o komentarz z wynikiem

+0

Nie. "Serwer może dowolnie wybrać dowolną wartość z tej niezagregowanej kolumny" https://dev.mysql.com/doc/refman/5.7/en/group-by-modifiers.html –

4
SELECT s.*, ss.* 
FROM student AS s 
LEFT JOIN (

SELECT * FROM student_story  
ORDER BY dateline DESC LIMIT 1 
) 
AS ss ON (ss.studentid = s.studentid) 
+0

Nauczyłem się ze wszystkich dostarczonych odpowiedzi ale twoja dała mi lepszą robotę. –

+0

To nie działa, ponieważ subselekcja zwraca tylko jeden wynik dla wszystkich uczniów, których nie można połączyć dla wszystkich z wyjątkiem pojedynczej ostatniej historii uczniów. – Roben

0

Musisz dodać identyfikator automatyczny i unikatowy w każdym rzędzie na tabeli student_story.

następnie można je rozróżnić. (Zakładamy studentstory.new_id)

select s.*, ss.* 
from student s 
left join student_story ss on ss.studentid = s.userid 
where ss.new_id = (select ss.new_id from student s 
    group by dateline 
    order by dateline desc 
    limit 1 
) 
1
SELECT 
    s.sale_id, 
    s.created_at, 
    p.created_at, 
    DATEDIFF(p.created_at, s.created_at) AS days 
FROM 
    pos_sales s 
     LEFT JOIN 
    pos_payments p ON p.sale_id = s.sale_id 
     AND 
    p.created_at = (SELECT 
      MAX(p2.created_at) 
     FROM 
      pos_payments p2 
     WHERE 
      p2.sale_id = p.sale_id) 
0

Innym podejściem jest dokonanie LEFT JOIN warunku NOT EXISTS(). W zależności od scenariusza może to dać nieco większą elastyczność; Jednak będzie to również pokazać zduplikowanych wyników, jeśli istnieją dwa wpisy o tym samym dateline jednego studenta:

SELECT s.*, ss.* 
FROM student AS s 
LEFT JOIN student_story AS ss ON ss.studentid = s.studentid AND NOT EXISTS 
    (SELECT * FROM student_story AS ss2 
    WHERE ss2.studentid = ss.studentid AND ss2.dateline > ss.dateline)