从具有最大日期的行的表中选择信息

问题描述 投票:0回答:5

我的桌子看起来像这样:

group    date      cash  checks
  1    1/1/2013     0      0
  2    1/1/2013     0      800
  1    1/3/2013     0      700
  3    1/1/2013     0      600
  1    1/2/2013     0      400
  3    1/5/2013     0      200

-- 不需要现金只是证明桌子上有更多信息

我想获取日期为最大值且检查大于 0 的每个唯一组。因此返回看起来像:

group    date     checks
  2    1/1/2013    800
  1    1/3/2013    700
  3    1/5/2013    200

尝试的代码:

SELECT group,MAX(date),checks
    FROM table
    WHERE checks>0
    GROUP BY group
    ORDER BY group DESC

问题是它给了我所有的日期和支票,而不仅仅是最大日期行。

使用 MS SQL Server 2005

sql sql-server-2005 greatest-n-per-group
5个回答
179
投票
SELECT group,MAX(date) as max_date
FROM table
WHERE checks>0
GROUP BY group

这适用于获取最大日期..将其加入您的数据以获取其他列:

Select group,max_date,checks
from table t
inner join 
(SELECT group,MAX(date) as max_date
FROM table
WHERE checks>0
GROUP BY group)a
on a.group = t.group and a.max_date = date

Inner Join 函数作为过滤器,只获取最大记录。

仅供参考,您的列名很糟糕,不要对列(组、日期、表)使用保留字。


52
投票

您可以像这样使用window MAX():

SELECT
  *, 
  max_date = MAX(date) OVER (PARTITION BY group)
FROM table

获取每个

group
的最大日期以及其他数据:

group  date      cash  checks  max_date
-----  --------  ----  ------  --------
1      1/1/2013  0     0       1/3/2013
2      1/1/2013  0     800     1/1/2013
1      1/3/2013  0     700     1/3/2013
3      1/1/2013  0     600     1/5/2013
1      1/2/2013  0     400     1/3/2013
3      1/5/2013  0     200     1/5/2013

使用上面的输出作为派生表,然后您只能获得

date
匹配
max_date
的行:

SELECT
  group,
  date,
  checks
FROM (
  SELECT
    *, 
    max_date = MAX(date) OVER (PARTITION BY group)
  FROM table
) AS s
WHERE date = max_date
;

得到想要的结果。

基本上,这类似于 @Twelfth 的建议,但避免了连接,因此可能更有效率。

您可以在 SQL Fiddle 尝试方法


5
投票

使用

in
会对性能产生影响。连接两个子查询不会产生相同的性能影响,可以这样完成:

SELECT *
  FROM (SELECT msisdn
              ,callid
              ,Change_color
              ,play_file_name
              ,date_played
          FROM insert_log
         WHERE play_file_name NOT IN('Prompt1','Conclusion_Prompt_1','silent')
        ORDER BY callid ASC) t1
       JOIN (SELECT MAX(date_played) AS date_played
               FROM insert_log GROUP BY callid) t2
         ON t1.date_played = t2.date_played

4
投票
SELECT distinct
  group, 
  max_date = MAX(date) OVER (PARTITION BY group), checks
FROM table

应该工作。


0
投票
SELECT *
INTO #temp
FROM
(
    VALUES
        (1, '1/1/2013', 0, 0),
        (2, '1/1/2013', 0, 800),
        (1, '1/3/2013', 0, 700),
        (3, '1/1/2013', 0, 600),
        (1, '1/2/2013', 0, 400),
        (3, '1/5/2013', 0, 200)
) x ([group], date, cash, checks);


-- Method 1
SELECT distinctgroup.[group],
       max_date.date,
       max_date.cash,
       max_date.checks
FROM
(SELECT DISTINCT [group] FROM #temp) distinctgroup
    CROSS APPLY
(
    SELECT TOP 1
           [group],
           date,
           cash,
           checks
    FROM #temp t
    WHERE distinctgroup.[group] = t.[group]
    ORDER BY date DESC
) max_date;



-- Method2

SELECT ot.[group],
        ot.date,
       ot.cash,
       ot.checks
       
FROM 
(SELECT  it.[group],
         it.date,
         it.cash,
         it.checks, ROW_NUMBER() OVER (PARTITION BY [group] ORDER BY date DESC) AS rownum 
FROM #temp it) ot
WHERE ot.rownum=1





DROP TABLE #temp;
© www.soinside.com 2019 - 2024. All rights reserved.