SQL - 聚合函数 - GROUP BY子句

时间:2012-12-19 20:32:29

标签: sql sql-server

我有以下查询:

select vkbr.vkID, vkbr.bid, vkbr.Date, vkbr.agID 
FROM camp c (NOLOCK)
JOIN ag (NOLOCK) ON ag.campID = c.id
JOIN vkbr WITH (NOLOCK) ON vkbr.agID = ag.id
where c.id = 648322
order by vkbr.vkID;

具有以下结果:

vkID        bid     Date                    agID
1072845175  NULL    2012-12-04 20:20:12.390 16074852
1072845177  0.74    2012-12-01 23:36:11.280 16074852
1072845177  0.18    2012-12-02 23:01:26.123 16074852
1072845177  0.72    2012-12-09 23:38:52.503 16074852
1072845177  0.62    2012-12-14 15:26:49.643 16074852
1072845178  2.91    2012-12-08 19:37:00.877 16074852
1072845178  0.73    2012-12-13 17:54:11.240 16074852
1072845178  2.70    2012-12-14 15:26:49.643 16074852

我需要按照vkID进行分组,获取最大值(日期)和最高出价(日期)以获得此结果:

1072845175  NULL    2012-12-04 20:20:12.390 16074852
1072845177  0.62    2012-12-14 15:26:49.643 16074852
1072845178  2.70    2012-12-14 15:26:49.643 16074852


select vkbr.vkID, MAX(vkbr.Date) as Date, MIN(vkbr.agID) as agID
FROM camp c (NOLOCK)
JOIN    ag (NOLOCK) ON ag.campID = c.id
JOIN    vkbr WITH (NOLOCK) ON vkbr.agID = ag.id
where c.id=648322
group by vkbr.vkID
having Max(vkbr.Date) is not null
and Max(Date) <= '2012-12-18';

由于我无法在SELECT语句中添加bid列 - 收到此错误: “出价”列在选择列表中无效,因为它不包含在聚合函数或GROUP BY子句中。

所以我尝试用临时表做这个:

create table #getBids ( 
vkID bigint not null,
Date datetime null,
agID bigint null);

insert into #getBids (vkID, Date, agID) 
select vkbr.vkID, MAX(vkbr.Date) as Date, MIN(vkbr.agID) as agID
FROM camp c (NOLOCK)
JOIN    ag (NOLOCK) ON ag.campID = c.id
JOIN    vkbr WITH (NOLOCK) ON vkbr.agID = ag.id
where c.id = 648322
group by vkbr.vkID
having Max(vkbr.Date) is not null
and Max(Date) <= '2012-12-18';

Now this gives me the result I want:

select vkbr.vkID, vkbr.bid from vkbr
inner join #getBids on vkbr.Date = #getBids.Date
and vkbr.agID = #getBids.agID
and vkbr.vkID = #getBids.vkID

我想知道无论如何要在一个查询中创建相同的结果而不创建临时表?任何帮助是极大的赞赏。

3 个答案:

答案 0 :(得分:2)

如果您使用的是SQL Server 2005或更高版本,则可以使用ROW_NUMBER()函数为每个MAX(Date)选择vkID行。

我无法使用您的架构对此进行测试,但我认为它的工作原理如下:

首先,声明公用表表达式(CTE)以向查询结果添加行号

with cte as
(    
    select vkbr.vkID, vkbr.bid, vkbr.Date, vkbr.agID, ROW_NUMBER() OVER (PARTITION BY vkbr.vkID ORDER BY vkbr.Date DESC) AS RowNumber
    FROM camp c (NOLOCK)
    JOIN ag (NOLOCK) ON ag.campID = c.id
    JOIN vkbr WITH (NOLOCK) ON vkbr.agID = ag.id
    where c.id = 648322
)

然后,SELECT仅在RowNumber = 1的位置。这将为您提供每个vkbr.vkID

的最新记录
select vkID, bid, Date, agID
from cte
where RowNumber = 1

答案 1 :(得分:1)

查询:

SELECT vkbr.vkID,
       vkbr.bid,
       vkbr.Date,
       vkbr.agID
FROM camp c (NOLOCK)
JOIN ag (NOLOCK) ON ag.campID = c.id
JOIN vkbr WITH (NOLOCK) ON vkbr.agID = ag.id
WHERE c.id = 648322
AND vkbr.Date = (SELECT MAX(v.Date)
                 FROM vkbr v2
                 WHERE v2.vkID = vkbr.vkID
                 AND v2.agID = vkbr.agID)
ORDER BY vkbr.vkID

示例查询:

<强> SQLFIDDLEExample

SELECT t1.*
FROM Table1 t1
WHERE t1.Date = (SELECT MAX(t2.Date)
                 FROM Table1 t2
                 WHERE t1.vkID = t2.vkID
                 AND t1.agID = t2.agID)

结果:

|       VKID |    BID |                            DATE |     AGID |
--------------------------------------------------------------------
| 1072845178 |   2.70 | December, 14 2012 15:26:49+0000 | 16074852 |
| 1072845177 |   0.62 | December, 14 2012 15:26:49+0000 | 16074852 |
| 1072845175 | (null) | December, 04 2012 20:20:12+0000 | 16074852 |

答案 2 :(得分:0)

您可以使用一个查询执行此操作。首先,查询必须通过vkID收集最大日期。接下来,它必须使用日期加入vkbr以获得实际出价。您可以使用sub-query,即点击此内容:

select vkID, bid, Date, agID
from
(
    select vkbr.vkID, MAX(vkbr.Date) as Date, MIN(vkbr.agID) as agID
    from camp c with (nolock)
    inner join ag with (nolock)
        on ag.campID = c.id
    inner join vkbr with (nolock)
        on vkbr.agID = ag.id
    where c.id = 648322
    group by vkbr.vkID
    having Max(vkbr.Date) is not null
    and Max(vkbr.Date) <= '2012-12-18';
) MaxDate
    inner join vkbr with (nolock)
        on vkbr.agID = MaxDate.agID
        and vkbr.Date = MaxDate.Date

我建议使用common table expression(CTE)而不是子查询。 CTE方法看起来像这样:

;with MaxDate (vkID, Date, agID) as
(
    select vkbr.vkID, MAX(vkbr.Date) as Date, MIN(vkbr.agID) as agID
    from ...
)
select ...
from MaxDate
inner join vkbr
    on vkbr.agID = MaxDate.agID
    and vkbr.Date = MaxDate.Date