【问题标题】:SQL - aggregate function - GROUP BY clauseSQL - 聚合函数 - GROUP BY 子句
【发布时间】:2012-12-07 07:03:50
【问题描述】:

我有以下疑问:

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 分组,获取 max(Date) 和 max(Date) 上的出价以获得此结果:

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

我想知道是否可以在一个查询中完成相同的结果而无需创建临时表?任何帮助是极大的赞赏。

【问题讨论】:

  • 您能在SQLFIDDLE 中创建您的表架构,或者请在这里向我们展示表架构吗?
  • 如果可能的话,礼貌地建议您在命名架构中更加详细。
  • 另外,我认为您在该查询中不可能遇到该错误。您不会在该特定查询中的任何地方拉出“出价”列。
  • +1 @blueSky 用于提出问题并展示您的尝试:)
  • @bobCodigo:如果您要求的话,我已经在 CREATE TABLE 中展示了架构。

标签: sql sql-server


【解决方案1】:

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

我无法使用您的架构对此进行测试,但我认为它会像这样工作:

首先,声明一个公用表表达式 (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

【讨论】:

    【解决方案2】:

    查询:

    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 |
    

    【讨论】:

    • 谢谢。从中学到了:)
    【解决方案3】:

    您可以通过一个查询来完成此操作。首先,查询必须通过 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
    

    【讨论】:

    • 虽然我已经接受了一个回复,但我尝试从其他回复中学习。请您给我一个完整的查询,以了解您的第一种方法,我无法弄清楚您要做什么。如果可能的话,还有一个带有 CTE 的 - 我看不出在哪里使用或提到了 CTE。
    • 子查询方法可以这样想:1) 获取分组的最大日期,然后 2) 加入该日期的表以获取实际出价。 CTE 是我和 Tim S 的答案中的 with 声明。
    猜你喜欢
    • 2022-10-25
    • 2013-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-27
    • 2010-11-15
    相关资源
    最近更新 更多