Bagaimana saya bisa MEMILIH baris dengan MAX(Kolom nilai), yang BERBEDA dengan kolom lain dalam SQL?

Meja saya adalah:

id  home  datetime     player   resource
---|-----|------------|--------|---------
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

Saya perlu untuk memilih masing-masing berbeda rumah memegang nilai maksimum datetime.

Hasilnya akan menjadi:

id  home  datetime     player   resource 
---|-----|------------|--------|---------
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

Saya telah mencoba:

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

Doesn't bekerja. Hasil-set memiliki 130 baris meskipun database memegang 187. Hasil mencakup beberapa duplikat dari rumah.

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

Nope. Memberikan semua catatan.

-- 3 ..something exotic: 

Dengan berbagai hasil.

Larutan

Anda begitu dekat! Semua yang perlu anda lakukan adalah memilih INVESTASI rumah dan max tanggal waktu, kemudian bergabung kembali ke topten meja di KEDUA bidang:

SELECT tt.*
FROM topten tt
INNER JOIN
    (SELECT home, MAX(datetime) AS MaxDateTime
    FROM topten
    GROUP BY home) groupedtt 
ON tt.home = groupedtt.home 
AND tt.datetime = groupedtt.MaxDateTime
Komentar (22)

Di sini berlaku T-SQL versi:

-- Test data
DECLARE @TestTable TABLE (id INT, home INT, date DATETIME, 
  player VARCHAR(20), resource INT)
INSERT INTO @TestTable
SELECT 1, 10, '2009-03-04', 'john', 399 UNION
SELECT 2, 11, '2009-03-04', 'juliet', 244 UNION
SELECT 5, 12, '2009-03-04', 'borat', 555 UNION
SELECT 3, 10, '2009-03-03', 'john', 300 UNION
SELECT 4, 11, '2009-03-03', 'juliet', 200 UNION
SELECT 6, 12, '2009-03-03', 'borat', 500 UNION
SELECT 7, 13, '2008-12-24', 'borat', 600 UNION
SELECT 8, 13, '2009-01-01', 'borat', 700

-- Answer
SELECT id, home, date, player, resource 
FROM (SELECT id, home, date, player, resource, 
    RANK() OVER (PARTITION BY home ORDER BY date DESC) N
    FROM @TestTable
)M WHERE N = 1

-- and if you really want only home with max date
SELECT T.id, T.home, T.date, T.player, T.resource 
    FROM @TestTable T
INNER JOIN 
(   SELECT TI.id, TI.home, TI.date, 
        RANK() OVER (PARTITION BY TI.home ORDER BY TI.date) N
    FROM @TestTable TI
    WHERE TI.date IN (SELECT MAX(TM.date) FROM @TestTable TM)
)TJ ON TJ.N = 1 AND T.id = TJ.id

EDIT Sayangnya, tidak ada PANGKAT() ALIH fungsi di MySQL. Tapi itu bisa ditiru, lihat Meniru Analisis (AKA Peringkat) Fungsi dengan MySQL. Jadi, ini adalah MySQL versi:

SELECT id, home, date, player, resource 
FROM TestTable AS t1 
WHERE 
    (SELECT COUNT(*) 
            FROM TestTable AS t2 
            WHERE t2.home = t1.home AND t2.date > t1.date
    ) = 0
Komentar (4)

Tercepat MySQL solusi, tanpa inner query dan tanpa GROUP BY:

SELECT m.*                    -- get the row that contains the max value
FROM topten m                 -- "m" from "max"
    LEFT JOIN topten b        -- "b" from "bigger"
        ON m.home = b.home    -- match "max" row with "bigger" row by `home`
        AND m.datetime < b.datetime           -- want "bigger" than "max"
WHERE b.datetime IS NULL      -- keep only if there is no bigger than max

Penjelasan:

Bergabung meja dengan dirinya sendiri menggunakan rumah kolom. Penggunaan LEFT JOIN memastikan semua baris dari tabel m muncul dalam hasil set. Orang-orang yang don't memiliki pertandingan di tabel b akan NULL untuk kolomb`.

Kondisi lainnya pada BERGABUNG meminta untuk mencocokkan baris dari b yang memiliki nilai yang lebih besar pada datetime kolom dari baris dari m.

Menggunakan data-data yang diposting di pertanyaan, LEFT JOIN akan menghasilkan pasangan ini:

+------------------------------------------+--------------------------------+
|              the row from `m`            |    the matching row from `b`   |
|------------------------------------------|--------------------------------|
| id  home  datetime     player   resource | id    home   datetime      ... |
|----|-----|------------|--------|---------|------|------|------------|-----|
| 1  | 10  | 04/03/2009 | john   | 399     | NULL | NULL | NULL       | ... | *
| 2  | 11  | 04/03/2009 | juliet | 244     | NULL | NULL | NULL       | ... | *
| 5  | 12  | 04/03/2009 | borat  | 555     | NULL | NULL | NULL       | ... | *
| 3  | 10  | 03/03/2009 | john   | 300     | 1    | 10   | 04/03/2009 | ... |
| 4  | 11  | 03/03/2009 | juliet | 200     | 2    | 11   | 04/03/2009 | ... |
| 6  | 12  | 03/03/2009 | borat  | 500     | 5    | 12   | 04/03/2009 | ... |
| 7  | 13  | 24/12/2008 | borat  | 600     | 8    | 13   | 01/01/2009 | ... |
| 8  | 13  | 01/01/2009 | borat  | 700     | NULL | NULL | NULL       | ... | *
+------------------------------------------+--------------------------------+

Akhirnya, WHERE terus-satunya pasangan yang memiliki NULL dalam kolomb(mereka ditandai dengan*pada tabel di atas); ini berarti, karena kondisi kedua dariBERGABUNGklausa, baris yang dipilih darimmemiliki nilai terbesar pada kolomdatetime`.

Membaca SQL Antipatterns: Menghindari Perangkap Pemrograman Database buku yang lain tips SQL.

Komentar (7)

Ini akan bekerja bahkan jika anda memiliki dua atau lebih baris untuk masing-masing rumah sama dengan DATETIME's:

SELECT id, home, datetime, player, resource
FROM   (
       SELECT (
              SELECT  id
              FROM    topten ti
              WHERE   ti.home = t1.home
              ORDER BY
                      ti.datetime DESC
              LIMIT 1
              ) lid
       FROM   (
              SELECT  DISTINCT home
              FROM    topten
              ) t1
       ) ro, topten t2
WHERE  t2.id = ro.lid
Komentar (8)

Saya pikir ini akan memberi anda hasil yang diinginkan:

SELECT   home, MAX(datetime)
FROM     my_table
GROUP BY home

TAPI jika anda membutuhkan kolom lain juga, hanya membuat yang bergabung dengan meja asli (check Michael La Voie jawaban)

Salam.

Komentar (3)

Sejak orang-orang tampaknya tetap berjalan ke thread ini (tanggal komentar berkisar 1,5 tahun) isn't ini jauh lebih sederhana:

SELECT * FROM (SELECT * FROM topten ORDER BY datetime DESC) tmp KELOMPOK DENGAN rumah

Tidak ada fungsi agregasi dibutuhkan...

Sorak-sorai.

Komentar (5)

Anda juga dapat mencoba yang satu ini dan untuk meja besar query kinerja akan menjadi lebih baik. Ia bekerja ketika ada lebih dari dua catatan untuk masing-masing rumah dan tanggal yang berbeda. Baik umum query MySQL adalah salah satu dari Michael La Voie di atas.

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

Atau dalam kasus Postgres atau mereka dbs yang memberikan analisis fungsi mencoba

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
Komentar (3)

Ini bekerja pada 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
Komentar (1)

Coba ini untuk 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
Komentar (0)
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
Komentar (0)

Cara lain untuk gt terbaru-turut per kelompok menggunakan sub query yang pada dasarnya menghitung pangkat untuk setiap baris per kelompok dan kemudian menyaring terbaru anda baris seperti dengan rank = 1

select a.*
from topten a
where (
  select count(*)
  from topten b
  where a.home = b.home
  and a.`datetime` < b.`datetime`
) +1 = 1

DEMO

Berikut ini adalah demo visual untuk peringkat yang ada untuk setiap baris untuk pemahaman yang lebih baik

Dengan membaca beberapa komentar bagaimana jika ada dua baris yang sama 'rumah' dan 'datetime' nilai-nilai bidang?

Pertanyaan di atas akan gagal dan akan kembali lebih dari 1 baris di atas situasi. Untuk menutupi situasi ini akan ada kebutuhan lain kriteria/parameter/kolom untuk menentukan baris mana yang harus diambil yang jatuh di atas situasi. Dengan melihat contoh data set saya berasumsi ada primary key kolom id yang harus di set ke auto increment. Jadi kita dapat menggunakan kolom ini untuk memilih yang paling baru-baru ini turut dengan mengutak-atik query yang sama dengan bantuan dari KASUS pernyataan seperti

select a.*
from topten a
where (
  select count(*)
  from topten b
  where a.home = b.home
  and  case 
       when a.`datetime` = b.`datetime`
       then a.id < b.id
       else a.`datetime` < b.`datetime`
       end
) + 1 = 1

DEMO

Pertanyaan di atas akan memilih baris dengan tertinggi id antara sama datetime nilai-nilai

visual demo untuk peringkat yang ada untuk masing-masing baris

Komentar (0)
SELECT c1, c2, c3, c4, c5 FROM table1 WHERE c3 = (select max(c3) from table)

SELECT * FROM table1 WHERE c3 = (select max(c3) from table1)
Komentar (0)

Berikut ini adalah MySQL versi yang mencetak hanya satu entri di mana ada duplikat MAX(datetime) dalam kelompok.

Anda bisa tes di sini http://www.sqlfiddle.com/#!2/0a4ae/1

Data Sampel

mysql> SELECT * from topten;
+------+------+---------------------+--------+----------+
| id   | home | datetime            | player | resource |
+------+------+---------------------+--------+----------+
|    1 |   10 | 2009-04-03 00:00:00 | john   |      399 |
|    2 |   11 | 2009-04-03 00:00:00 | juliet |      244 |
|    3 |   10 | 2009-03-03 00:00:00 | john   |      300 |
|    4 |   11 | 2009-03-03 00:00:00 | juliet |      200 |
|    5 |   12 | 2009-04-03 00:00:00 | borat  |      555 |
|    6 |   12 | 2009-03-03 00:00:00 | borat  |      500 |
|    7 |   13 | 2008-12-24 00:00:00 | borat  |      600 |
|    8 |   13 | 2009-01-01 00:00:00 | borat  |      700 |
|    9 |   10 | 2009-04-03 00:00:00 | borat  |      700 |
|   10 |   11 | 2009-04-03 00:00:00 | borat  |      700 |
|   12 |   12 | 2009-04-03 00:00:00 | borat  |      700 |
+------+------+---------------------+--------+----------+

Versi MySQL dengan User variabel

SELECT *
FROM (
    SELECT ord.*,
        IF (@prev_home = ord.home, 0, 1) AS is_first_appear,
        @prev_home := ord.home
    FROM (
        SELECT t1.id, t1.home, t1.player, t1.resource
        FROM topten t1
        INNER JOIN (
            SELECT home, MAX(datetime) AS mx_dt
            FROM topten
            GROUP BY home
          ) x ON t1.home = x.home AND t1.datetime = x.mx_dt
        ORDER BY home
    ) ord, (SELECT @prev_home := 0, @seq := 0) init
) y
WHERE is_first_appear = 1;
+------+------+--------+----------+-----------------+------------------------+
| id   | home | player | resource | is_first_appear | @prev_home := ord.home |
+------+------+--------+----------+-----------------+------------------------+
|    9 |   10 | borat  |      700 |               1 |                     10 |
|   10 |   11 | borat  |      700 |               1 |                     11 |
|   12 |   12 | borat  |      700 |               1 |                     12 |
|    8 |   13 | borat  |      700 |               1 |                     13 |
+------+------+--------+----------+-----------------+------------------------+
4 rows in set (0.00 sec)

Menerima Jawaban' outout

SELECT tt.*
FROM topten tt
INNER JOIN
    (
    SELECT home, MAX(datetime) AS MaxDateTime
    FROM topten
    GROUP BY home
) groupedtt ON tt.home = groupedtt.home AND tt.datetime = groupedtt.MaxDateTime
+------+------+---------------------+--------+----------+
| id   | home | datetime            | player | resource |
+------+------+---------------------+--------+----------+
|    1 |   10 | 2009-04-03 00:00:00 | john   |      399 |
|    2 |   11 | 2009-04-03 00:00:00 | juliet |      244 |
|    5 |   12 | 2009-04-03 00:00:00 | borat  |      555 |
|    8 |   13 | 2009-01-01 00:00:00 | borat  |      700 |
|    9 |   10 | 2009-04-03 00:00:00 | borat  |      700 |
|   10 |   11 | 2009-04-03 00:00:00 | borat  |      700 |
|   12 |   12 | 2009-04-03 00:00:00 | borat  |      700 |
+------+------+---------------------+--------+----------+
7 rows in set (0.00 sec)
Komentar (2)

Mengapa tidak menggunakan: PILIH rumah, MAX(datetime) SEBAGAI MaxDateTime,pemain,sumber daya DARI topten KELOMPOK DENGAN rumah Apa aku melewatkan sesuatu?

Komentar (4)

Coba ini

select * from mytable a join
(select home, max(datetime) datetime
from mytable
group by home) b
 on a.home = b.home and a.datetime = b.datetime

Salam K

Komentar (3)

ini adalah query yang anda butuhkan:

 SELECT b.id, a.home,b.[datetime],b.player,a.resource FROM
 (SELECT home,MAX(resource) AS resource FROM tbl_1 GROUP BY home) AS a

 LEFT JOIN

 (SELECT id,home,[datetime],player,resource FROM tbl_1) AS b
 ON  a.resource = b.resource WHERE a.home =b.home;
Komentar (1)

@Mic jawaban Yang diterima akan bekerja dengan baik di sebagian besar kasus, tetapi gagal untuk satu untuk sebagai berikut.

Dalam kasus jika ada 2 baris yang memiliki HomeID dan Datetime yang sama dengan query akan mengembalikan baris kedua, tidak berbeda HomeID seperti yang diperlukan, untuk itu tambahkan Berbeda dalam query seperti di bawah ini.

SELECT DISTINCT tt.home  , tt.MaxDateTime
FROM topten tt
INNER JOIN
    (SELECT home, MAX(datetime) AS MaxDateTime
    FROM topten
    GROUP BY home) groupedtt 
ON tt.home = groupedtt.home 
AND tt.datetime = groupedtt.MaxDateTime
Komentar (4)