每当我使用SQL聚合函数时,我发现它们的实用程序因Group By子句的需要而受到阻碍。我总是不得不使用一堆嵌套选择来获得我想要的东西。我想知道我是不是没有正确使用这些功能。
例如。如果我有以下数据:
ID Fruit Color CreatedDate
-- ----- ----- -----------
1 Apple Red 2014-07-25 12:41:44.000
2 Apple Green 2014-07-31 10:01:01.000
3 Apple Blue 2014-07-10 07:05:51.317
4 Orange Orange 2014-06-26 13:42:35.360
我想获得最近创建的苹果记录。如果我用这个:
SELECT [ID]
,[Fruit]
,[Color]
,max([CreatedDate])
FROM [CCM].[dbo].[tblFruit]
WHERE Fruit = 'Apple'
GROUP BY ID, Fruit, Color
它给了我所有三个Apple条目,而不仅仅是最新条目,因为我被迫在group by子句中包含所有其他列。真的,我只是希望它按水果分组并给我最新记录(整个记录,而不仅仅是列的一部分)。
为了得到我想要的东西,我必须使用它:
SELECT [ID]
,[Fruit]
,[Color]
,[CreatedDate]
FROM [CCM].[dbo].[tblFruit]
WHERE Fruit = 'Apple' AND CreatedDate IN
(SELECT max([CreatedDate]) as [CreatedDate]
FROM [CCM].[dbo].[tblFruit]
WHERE Fruit = 'Apple')
这对我来说很丑陋,在SQL中忘记聚合并在.NET中执行任何min,max,count等会更容易。
这是使用聚合的正确方法(使用嵌套选择)还是我做错了?
答案 0 :(得分:3)
对于这种情况,您最好使用像row_number()
select id, fruit, color, createddate
from
(
select id, fruit, color, createddate,
row_number() over(partition by fruit order by createddate desc) seq
from tblFruit
) d
where seq = 1;
请参阅Demo
使用此功能,您可以按fruit
对数据进行分区,并按fruit
对每个createddate
内的行进行排序。通过将row_number()
放在子查询中,您将返回每个fruit
的第一行 - 这些是带有seq=1
的项目。如果您要查找仅Apple
的项目,则可以轻松添加WHERE
子句。
您还可以使用子查询为每个max(createddate)
选择fruit
来获得结果:
select f.id,
f.fruit,
f.color,
f.createddate
from tblFruit f
inner join
(
select fruit, max(createddate) CreatedDate
from tblfruit
group by fruit
) d
on f.fruit = d.fruit
and f.createddate = d.createddate;
见Demo。您得到相同的结果,但仍然可以对此应用WHERE
过滤器。
答案 1 :(得分:0)
根据您的评论,您可以使用CTE来构建每个水果的最大日期列表。然后,您可以将其加入到原始表中,以获得与该最大日期匹配的完整行。
SQL Fiddle
with MaxDates as
(select
fruit,
max(createddate) as maxdate
from
table1
group by
fruit)
select
t1.*
from
table1 t1
inner join maxdates md
on t1.fruit = md.fruit
and t1.createddate = md.maxdate
顺便说一下,你真的不想尝试将这种功能推向你的应用程序。在SQL中做这种事情是无限好的。如果没有别的,请考虑一下你的表中是否有数百万行。您当然不希望将数百万行从数据库中推送到应用程序,以将其总计为单行等。
答案 2 :(得分:0)
如何将TOP与ORDER BY一起使用
SELECT TOP(1) *
FROM [CCM].[dbo].[tblFruit]
WHERE Fruit = 'Apple'
ORDER BY [CreatedDate] DESC