【问题标题】:SQL Group By One Field and Order By Another FieldSQL 按一个字段分组并按另一个字段排序
【发布时间】:2009-12-02 23:53:09
【问题描述】:

桌子:

declare @Table table (    
 id int,    
 ticketid int,    
 sponsor int,    
 dev int,
 qa int,
 savedate datetime
)

insert into @Table values (1,100,22,0, 0, '2008-10-29 11:17:59.527')
insert into @Table values (2,100,5,0, 0, '2008-10-29 11:00:37.030')
insert into @Table values (3,101,22,0, 0, '2009-10-29 11:10:27.687')
insert into @Table values (5,101,44,0, 0, '2008-10-31 12:07:52.917')
insert into @Table values (6,101,32,0, 0, '2009-06-30 08:16:12.343')
insert into @Table values (7,101,44,0, 0, '2009-10-31 10:12:11.369')

我正在尝试选择前 1 个最大保存数据,其中 recordid 是某个记录,按赞助商分组。

我的进步:

select max(savedate)
from @Table
where ticketid = 101
group by sponsor

返回

2009-10-29 11:10:27.687
2009-06-30 08:16:12.343
2009-10-31 10:12:11.370

关闭,我的分组正确,但我想要前 1 个最近的日期。所以我这样做:

select top 1 max(savedate)
from @Table
where ticketid = 101
group by sponsor

返回

2009-10-29 11:10:27.687

哇哦,明白了,该休息一下了..等等..这不是你最近的约会!让我们尝试通过 savedate 来订购这些

select top 1 max(savedate)
from @Table
where ticketid = 101
group by sponsor
order by savedate desc

哦不!可怕的:

“列“@Table.savedate”无效 在 ORDER BY 子句中,因为它是 不包含在任一聚合中 函数或 GROUP BY 子句。”

但 saveate 已聚合在选择列表中!我该怎么做?

【问题讨论】:

    标签: sql-server sql-server-2005 tsql


    【解决方案1】:

    在输入这个东西并确保我没有遗漏任何细节之后,我在最后想出了答案。我想无论如何我都会添加它,以便我或其他任何人稍后可以找到它,如果他们像我在这种情况下一样短视。

    select top 1 max(savedate) as date
    from @Table
    where ticketid = 101
    group by sponsor
    order by date desc
    

    max(savedate) 和 savedate 不一样!别名然后引用聚合工作完美:

    2009-10-31 10:12:11.370
    

    希望这对某人有所帮助。

    【讨论】:

      【解决方案2】:
      select top 1 max(savedate)
      from @Table
      where ticketid = 101
      group by sponsor
      order by max(savedate) desc
      

      【讨论】:

      • 是的,差不多就是这样。出于好奇,您知道 order by 子句中的 max(savedate) 是否会重新计算?如果是这样,我想别名将是要走的路。我想MS会想到这一点并以某种方式缓存它。 SQL 管理器中的查询计划是否为您提供此类问题的答案?那个查询计划图对我来说是个谜。
      【解决方案3】:

      您可能希望连同MAX(savedate) 一起退回赞助商。

      如果你没有注意到这个查询:

      SELECT  MAX(savedate)
      FROM    @Table
      WHERE   ticketid = 101
      

      与您的解决方案完全相同

      select top 1 max(savedate) as date
      from @Table
      where ticketid = 101
      group by sponsor
      order by date desc
      

      ,同时效率更高。

      或者,您可以执行以下操作:

      SELECT  TOP 1 sponsor, savedate
      FROM    @Table
      WHERE   ticketid = 101
      ORDER BY
              savedate DESC
      

      更新:

      此查询将返回任务最后分配给当前赞助商的日期:

      declare @Table table (    
       id int PRIMARY KEY,    
       ticketid int,    
       sponsor int,    
       dev int,
       qa int,
       savedate datetime
      )
      
      insert into @Table values (1,100,22,0, 0, '2008-10-29 11:17:59.527')
      insert into @Table values (2,100,5,0, 0, '2008-10-29 11:00:37.030')
      insert into @Table values (3,101,22,0, 0, '2009-10-29 11:10:27.687')
      insert into @Table values (5,101,44,0, 0, '2008-10-31 12:07:52.917')
      insert into @Table values (6,101,32,0, 0, '2009-06-30 08:16:12.343')
      insert into @Table values (7,101,44,0, 0, '2009-10-30 10:12:11.369')
      insert into @Table values (8,101,44,1, 0, '2009-10-31 10:12:11.369')
      
      ;WITH    rows AS
              (
              SELECT  *, ROW_NUMBER() OVER (PARTITION BY ticketid ORDER BY savedate DESC) AS rn
              FROM    @Table
              )
      SELECT  rl.sponsor, ro.savedate
      FROM    rows rl
      CROSS APPLY
              (
              SELECT  TOP 1 rc.savedate
              FROM    rows rc
              JOIN    rows rn
              ON      rn.ticketid = rc.ticketid
                      AND rn.rn = rc.rn + 1
                      AND rn.sponsor <> rc.sponsor
              WHERE   rc.ticketid = rl.ticketid
              ORDER BY
                      rc.rn
              ) ro
      WHERE   rl.rn = 1
      

      我在测试数据中为赞助商44 添加了一条记录。

      查询将返回行 17,因为赞助商在行 8 中没有更改。

      【讨论】:

      • 是的,有点忘了补充。我想按赞助商分组,因为我关心该字段的值何时从记录更改为记录。如果 dev 或 qa 发生变化,但赞助商没有,那么我不希望它出现在我的结果集中。
      • 我的查询在返回的结果方面和你的完全一样。 “开发或质量保证更改”是什么意思?
      • 也许一些上下文会有所帮助。此表跟踪错误跟踪程序中的工单何时更改了分配字段之一。它可以分配给发起人、QA 团队成员或开发人员。如果更改了这些分配中的任何一个,则会将一条记录插入到此表中,其中包含每个分配类型的当前分配用户(可能是糟糕的设计)。我想看看赞助商将票分配给他们多长时间,无论开发或质量保证分配是否已更改。这就是我按赞助商分组的原因。然后我将 savedate 与当前日期进行比较并获取天数。
      • 哇,花哨的东西。所以我已经意识到,正如你所知道的,我所追求的和我想出的并不相同:) 在这种情况下,我最终追求的是赞助商最后一次改变,而不是当赞助商以外的任何事情发生变化时。那么我可以通过将 AND rn.sponsor rc.sponsor 更改为 AND rn.sponsor = rc.sponsor 来实现吗?
      • 这将返回您上次更改赞助商的时间。查看我的测试数据。赞助商不会在行78 之间更改,这就是我不返回行8 的原因。但是赞助商确实在67 行之间发生了变化,并且7 行保留了赞助商更改的日期,这就是我返回7 行的原因。
      猜你喜欢
      • 2014-06-23
      • 2016-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-19
      • 1970-01-01
      相关资源
      最近更新 更多