mysql - मैं एसक्यूएल में किसी अन्य कॉलम द्वारा MAX(कॉलम मान), DISTINCT के साथ पंक्तियों को कैसे चुन सकता हूं?




greatest-n-per-group (12)

मेरी मेज है:

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

मुझे डेटाटाइम के अधिकतम मूल्य वाले प्रत्येक विशिष्ट home का चयन करने की आवश्यकता है।

परिणाम होगा:

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

मैं प्रयास कर चुका हूं:

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

काम नहीं करता परिणाम-सेट में 130 पंक्तियां हैं, हालांकि डेटाबेस में 187 हैं। परिणाम में home कुछ डुप्लीकेट शामिल 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 

नहीं। सभी रिकॉर्ड देता है।

-- 3 ..something exotic: 

विभिन्न परिणामों के साथ।


@Michae स्वीकार्य उत्तर ज्यादातर मामलों में ठीक काम करेगा लेकिन यह नीचे के लिए एक के लिए विफल रहता है।

अगर होमआईडी और डेटाटाइम वाली 2 पंक्तियां हों तो क्वेरी दोनों पंक्तियों को वापस कर देगी, अलग-अलग होमआईडी आवश्यक नहीं है, इसके लिए नीचे क्वेरी में अलग जोड़ें।

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

SQL सर्वर के लिए इसे आज़माएं:

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

इसे इस्तेमाल करे

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

सादर के


उप-क्वेरी का उपयोग करके प्रति समूह की सबसे हाल की पंक्ति को gt करने का एक और तरीका जो मूल रूप से प्रति पंक्ति प्रत्येक पंक्ति के लिए रैंक की गणना करता है और फिर रैंक = 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

बेहतर समझ के लिए प्रत्येक पंक्ति के लिए रैंक संख्या के लिए दृश्य डेमो यहां दिया गया है

कुछ टिप्पणियों को पढ़ने के बारे में क्या है यदि दो पंक्तियां हैं जिनमें 'होम' और 'डेटाटाइम' फ़ील्ड मान हैं?

उपरोक्त क्वेरी विफल हो जाएगी और उपर्युक्त स्थिति के लिए 1 से अधिक पंक्तियां वापस कर देगी। इस स्थिति को कवर करने के लिए उपरोक्त स्थिति में कौन सी पंक्ति ली जानी चाहिए, यह तय करने के लिए एक और मानदंड / पैरामीटर / कॉलम की आवश्यकता होगी। नमूना डेटा सेट देखकर मुझे लगता है कि एक प्राथमिक कुंजी कॉलम id जिसे स्वत: वृद्धि के लिए सेट किया जाना चाहिए। इसलिए हम इस कॉलम का उपयोग CASE स्टेटमेंट की मदद से एक ही क्वेरी को ट्वीव करके सबसे हालिया पंक्ति चुनने के लिए कर सकते हैं

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

उपर्युक्त क्वेरी उसी datetime मानों के बीच उच्चतम आईडी वाले पंक्ति को datetime

प्रत्येक पंक्ति के लिए रैंक संख्या के लिए दृश्य डेमो


चूंकि लोग इस धागे में चलते रहते हैं (टिप्पणी तिथि 1.5 वर्ष से है) यह इतना आसान नहीं है:

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

कोई समेकन कार्यों की आवश्यकता नहीं है ...

चीयर्स।


तुम बहुत करीब हो! आपको बस इतना करना है कि घर और उसके अधिकतम दिनांक समय का चयन करें, फिर दोनों क्षेत्रों में topten तालिका में शामिल हों:

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

यह ओरेकल पर काम करता है:

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

यह तब भी काम करेगा जब आपके पास प्रत्येक home लिए दो या दो से अधिक पंक्तियां बराबर DATETIME साथ होंगी:

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

यहां टी-एसक्यूएल संस्करण चला गया है:

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

संपादित करें
दुर्भाग्य से, MySQL में कोई रैंक () फ़ंक्शन नहीं है।
लेकिन यह नकल किया जा सकता है, MySQL के साथ Emulating विश्लेषणात्मक (AKA रैंकिंग) कार्यों को देखें
तो यह MySQL संस्करण है:

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

यहां MySQL संस्करण है जो केवल एक प्रविष्टि को प्रिंट करता है जहां समूह में MAX (डेटाटाइम) डुप्लीकेट होते हैं।

आप यहां http://www.sqlfiddle.com/#!2/0a4ae/1 परीक्षण कर सकते हैं

नमूना डेटा

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

उपयोगकर्ता चर के साथ MySQL संस्करण

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)

स्वीकृत उत्तर 'आउटआउट

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)

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

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)





greatest-n-per-group