كيف يمكن تحديد الصفوف مع ماكس(قيمة العمود) ، متميزة من جانب آخر عمود في SQL ؟

StackOverflow https://stackoverflow.com/questions/612231

سؤال

الجدول الخاص بي:

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 عقد أقصى قيمة datetime.

النتيجة ستكون:

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.

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

مع نتائج مختلفة.

هل كانت مفيدة؟

المحلول

كنت قريبا جدا!كل ما عليك القيام به هو اختيار كل من المنزل و ماكس التاريخ الوقت, ثم الانضمام إلى 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

نصائح أخرى

هنا يذهب T-SQL الإصدار:

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

تحرير
للأسف لا يوجد رتبة() أكثر من وظيفة في الخلية.
ولكن يمكن أن يكون نموذجا يحتذى به ، انظر محاكاة التحليلية (الملقب الترتيب) مع وظائف الخلية.
لذلك هذا هو الخلية الإصدار:

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 الحل دون الداخلية الاستعلامات بدون 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

تفسير:

الانضمام إلى طاولة المفاوضات مع نفسها باستخدام home العمود.استخدام LEFT JOIN يضمن كافة الصفوف من الجدول m تظهر في مجموعة النتائج.تلك التي ليس لديها مباراة في الجدول b سوف يكون NULLs الأعمدة من b.

أما الشرط على JOIN يطلب إلى المباراة الوحيد الصفوف من b التي لها أكبر قيمة datetime عمود من الصف من m.

باستخدام البيانات المنشورة في السؤال ، LEFT JOIN سوف تنتج هذه أزواج:

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

أخيرا ، WHERE شرط يبقى فقط أن أزواج NULLs في الأعمدة من b (يتم وضع علامة مع * في الجدول أعلاه) ؛ وهذا يعني بسبب الشرط الثاني من JOIN شرط الصف مختارة من m أكبر قيمة في العمود datetime.

قراءة SQL Antipatterns:تجنب المزالق برمجة قواعد البيانات كتاب الأخرى SQL النصائح.

هذا العمل حتى إذا كان لديك اثنين أو أكثر من الصفوف لكل 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

أعتقد هذا وسوف تعطيك النتيجة المرجوة:

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

ولكن إذا كنت بحاجة إلى الأعمدة الأخرى كذلك, جعل مجرد الانضمام إلى الجدول الأصلي (check Michael La Voie الإجابة)

مع أطيب التحيات.

لأن الناس يبدو للحفاظ على التوالي في هذا الموضوع (تاريخ التعليق يتراوح من 1.5 سنة) أليس هذا أبسط من ذلك بكثير:

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

لا تجميع المهام المطلوبة...

الهتافات.

يمكنك أيضا محاولة هذا واحد كبير جداول الاستعلام الأداء سيكون أفضل.يعمل عندما يكون هناك أكثر من اثنين من السجلات في كل منزل وفي تواريخ مختلفة.أفضل العامة الاستعلام الخلية هي واحدة من مايكل La Voie أعلاه.

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

أو في حالة بوستجرس أو تلك dbs التي توفر الوظائف التحليليه في محاولة

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

وهذا يعمل على أوراكل:

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

جرب هذا ل 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
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)

هنا هو نسخة الخلية الذي يطبع إدخال واحد فقط حيث هناك التكرارات ماكس(التاريخ والوقت) في مجموعة.

يمكنك اختبار هنا 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)

الإجابات المقبولة' 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)

طريقة أخرى 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

هنا عرض مرئي لرتبة لا لكل صف من أجل فهم أفضل

من خلال قراءة بعض التعليقات ماذا عن إذا كان هناك اثنين من الصفوف التي لها نفس 'الوطن' و 'datetime' حقل القيم ؟

الاستعلام أعلاه سوف تفشل وسوف يعود أكثر من 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 القيم

عرض مرئي لرتبة لا لكل صف

جرب هذا

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

تحياتي K

لماذا لا تستخدم:حدد المنزل, ماكس(التاريخ والوقت) كما MaxDateTime,لاعب,الموارد من topten والعد مجموعة من المنزل هل فاتني شيء ؟

هذا هو الاستعلام تحتاج:

 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;

@Michae الجواب المقبول سوف تعمل بشكل جيد في معظم الحالات ولكنها تفشل واحدة على النحو التالي.

في حالة إذا كانت هناك 2 الصفوف وجود HomeID و التاريخ والوقت نفس الاستعلام سيعود كل الصفوف وليس متميزة HomeID كما هو مطلوب ، إضافة متميزة في الاستعلام كما يلي.

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
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top