909 Stimmen

Wie kann ich SELECT Zeilen mit MAX(Spaltenwert), PARTITION durch eine andere Spalte in MYSQL?

Mein Tisch ist:

id

Startseite

datetime

Spieler

Ressource

1

10

04/03/2009

john

399

2

11

04/03/2009

juliet

244

5

12

04/03/2009

borat

555

3

10

03/03/2009

john

300

4

11

03/03/2009

juliet

200

6

12

03/03/2009

borat

500

7

13

24/12/2008

borat

600

8

13

01/01/2009

borat

700

Ich muss jedes einzelne Element auswählen home die den maximalen Wert von datetime .

Das Ergebnis wäre:

id

Startseite

datetime

Spieler

Ressource

1

10

04/03/2009

john

399

2

11

04/03/2009

juliet

244

5

12

04/03/2009

borat

555

8

13

01/01/2009

borat

700

Ich habe es versucht:

-- 1 ..by the MySQL manual: 

SELECT DISTINCT
  home,
  id,
  datetime AS dt,
  player,
  resource
FROM topten t1
WHERE datetime = (SELECT
  MAX(t2.datetime)
FROM topten t2
GROUP BY home)
GROUP BY datetime
ORDER BY datetime DESC

Funktioniert nicht. Die Ergebnismenge hat 130 Zeilen, obwohl die Datenbank 187 Zeilen enthält. Das Ergebnis enthält einige Duplikate von home .

-- 2 ..join

SELECT
  s1.id,
  s1.home,
  s1.datetime,
  s1.player,
  s1.resource
FROM topten s1
JOIN (SELECT
  id,
  MAX(datetime) AS dt
FROM topten
GROUP BY id) AS s2
  ON s1.id = s2.id
ORDER BY datetime 

Nö. Es gibt alle Aufzeichnungen.

-- 3 ..something exotic: 

Mit unterschiedlichen Ergebnissen.

0 Stimmen

16voto

MJB Punkte 211

Da die Leute anscheinend immer wieder auf diesen Thread stoßen (das Datum der Kommentare reicht von 1,5 Jahren), ist das nicht viel einfacher:

SELECT * FROM (SELECT * FROM topten ORDER BY datetime DESC) tmp GROUP BY home

Keine Aggregationsfunktionen erforderlich...

Zum Wohl.

7 Stimmen

Das scheint nicht zu funktionieren. Fehlermeldung: Die Spalte 'x' ist in der Auswahlliste ungültig, da sie weder in einer Aggregatfunktion noch in der GROUP BY-Klausel enthalten ist.

0 Stimmen

Dies wird definitiv nicht in SQL Server oder Oracle funktionieren, obwohl es so aussieht, als ob es in MySQL funktionieren könnte.

0 Stimmen

Das ist wirklich schön! Wie funktioniert das? Durch die Verwendung von DESC und der Standard-Gruppenrückgabespalte? Wenn ich es also in datetime ASC ändere, würde es die früheste Zeile für jedes Haus zurückgeben?

11voto

Shiva Punkte 631

Sie können auch diese Variante ausprobieren und bei großen Tabellen wird die Abfrageleistung besser sein. Sie funktioniert, wenn es nicht mehr als zwei Datensätze für jedes Haus gibt und ihre Daten unterschiedlich sind. Eine bessere allgemeine MySQL-Abfrage ist die von Michael La Voie oben.

SELECT t1.id, t1.home, t1.date, t1.player, t1.resource
FROM   t_scores_1 t1 
INNER JOIN t_scores_1 t2
   ON t1.home = t2.home
WHERE t1.date > t2.date

Oder im Falle von Postgres oder anderen Datenbanken, die analytische Funktionen anbieten, versuchen Sie

SELECT t.* FROM 
(SELECT t1.id, t1.home, t1.date, t1.player, t1.resource
  , row_number() over (partition by t1.home order by t1.date desc) rw
 FROM   topten t1 
 INNER JOIN topten t2
   ON t1.home = t2.home
 WHERE t1.date > t2.date 
) t
WHERE t.rw = 1

0 Stimmen

Ist diese Antwort richtig? Ich habe versucht, es zu verwenden, aber es scheint nicht den Datensatz mit dem neuesten Datum für "home" auszuwählen, sondern entfernt nur den Datensatz mit dem ältesten Datum. Hier ist ein Beispiel: SQLfiddle

1 Stimmen

@kidOfDeath - Aktualisierte meine Antwort mit Kontext und Postgres-Abfrage

0 Stimmen

Con SQLite Die erste ist sehr viel langsamer als die Version von La Voie, wenn es keinen Index für die übereinstimmende Spalte gibt (d. h. "home").

9voto

Kaptah Punkte 9373
SELECT  tt.*
FROM    TestTable tt 
INNER JOIN 
        (
        SELECT  coord, MAX(datetime) AS MaxDateTime 
        FROM    rapsa 
        GROUP BY
                krd 
        ) groupedtt
ON      tt.coord = groupedtt.coord
        AND tt.datetime = groupedtt.MaxDateTime

8voto

SysDragon Punkte 9370

Versuchen Sie dies für SQL Server:

WITH cte AS (
   SELECT home, MAX(year) AS year FROM Table1 GROUP BY home
)
SELECT * FROM Table1 a INNER JOIN cte ON a.home = cte.home AND a.year = cte.year

8voto

FerranB Punkte 33783

Dies funktioniert bei Oracle:

with table_max as(
  select id
       , home
       , datetime
       , player
       , resource
       , max(home) over (partition by home) maxhome
    from table  
)
select id
     , home
     , datetime
     , player
     , resource
  from table_max
 where home = maxhome

3 Stimmen

Wie wird der maximale Zeitpunkt ausgewählt? Er bat darum, nach Wohnort zu gruppieren und den maximalen Zeitpunkt auszuwählen. Ich sehe nicht, wie dies tut, dass.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X