【问题标题】:How to group by a Calculated Field如何按计算字段分组
【发布时间】:2013-03-31 19:51:43
【问题描述】:

我需要按 SQL Server 2005/2008 中的计算字段分组。

我有以下sql:

select dateadd(day, -7, Convert(DateTime, mwspp.DateDue) + (7 - datepart(weekday, mwspp.DateDue))),
sum(mwspp.QtyRequired)
from manufacturingweekshortagepartpurchasing mwspp
where mwspp.buildScheduleSimID = 10109 and mwspp.partID = 8366
group by mwspp.DateDue
order by mwspp.DateDue

我需要按计算结果分组,而不是 group by mwspp.DateDue。有可能吗?

提前致谢

【问题讨论】:

    标签: sql sql-server tsql group-by


    【解决方案1】:

    当然,只需将相同的计算添加到GROUP BY 子句:

    select dateadd(day, -7, Convert(DateTime, mwspp.DateDue) + (7 - datepart(weekday, mwspp.DateDue))),
    sum(mwspp.QtyRequired)
    from manufacturingweekshortagepartpurchasing mwspp
    where mwspp.buildScheduleSimID = 10109 and mwspp.partID = 8366
    group by dateadd(day, -7, Convert(DateTime, mwspp.DateDue) + (7 - datepart(weekday, mwspp.DateDue)))
    order by dateadd(day, -7, Convert(DateTime, mwspp.DateDue) + (7 - datepart(weekday, mwspp.DateDue)))
    

    评论后编辑:

    就像所有关于优化器的问题一样,答案实际上是“视情况而定”,但很可能只会执行一次 - 您会在执行计划中将其视为 Compute Scalar 运算符.

    基于这个计算标量操作,优化器将决定如何执行实际的聚合。

    这里的其他答案(CTE/子查询等)都同样有效,但并没有真正改变逻辑 - 最终它们将执行类似的操作。 SQL Server 可能会以不同的方式对待它们,但不太可能。但是,它们将有助于提高可读性。

    如果您担心效率,可以考虑几个选项,例如将计算设置为 persisted computed column 并在索引中使用它,或者将中间结果添加到临时表中。

    真正确定的唯一方法是在对典型数据集运行查询时检查执行计划/IO 统计信息,看看您是否对性能感到满意;如果没有,也许可以研究上述选项之一。

    【讨论】:

    • 谢谢,但这不是有点贵吗?还是 sql server 以某种方式对其进行优化以仅执行一次计算?
    • @Jonny,我已经添加了一些想法 - 最好的办法是对您的数据进行测试,看看是否可以 - 如果不是,请查看其他选项以提高效率点。
    • 就个人而言,我希望所有四个答案的性能几乎相同 - 主要区别在于我和 Bluefeet 使用的方法比其他答案更干燥,因为我们只需包含一次计算。
    • @MarkBannister,同意,这就是我希望在编辑后的评论中提出的观点;人们会期望优化者在物理操作方面平等对待它们。因此,除了对用户来说最易读/最有效的东西 - 如果我自己这样做,我会考虑使用 CTE,而不是简单复杂的场景。
    【解决方案2】:

    如果您想GROUP BY dateadd 计算,那么您需要将该公式放在GROUP BY 子句中,或者您可以将查询包装在另一个 SELECT 中:

    select DateCalc,
      sum(QtyRequired) TotalQty
    from
    (
      select mwspp.DateDue,
        dateadd(day, -7, Convert(DateTime, mwspp.DateDue) + (7 - datepart(weekday, mwspp.DateDue))) DateCalc,
        mwspp.QtyRequired
      from manufacturingweekshortagepartpurchasing mwspp
      where mwspp.buildScheduleSimID = 10109 
        and mwspp.partID = 8366
    ) src
    group by DateCalc
    order by DateCalc
    

    【讨论】:

      【解决方案3】:

      有几种方法可以做到这一点 - 一种涉及使用 CTE:

      with cte as 
      (select m.*, 
              dateadd(day, -7, Convert(DateTime, DateDue) + (7 - datepart(weekday, DateDue))) datecalc
       from manufacturingweekshortagepartpurchasing m)
      select datecalc, sum(QtyRequired)
      from cte
      where buildScheduleSimID = 10109 and partID = 8366
      group by datecalc
      order by datecalc
      

      【讨论】:

      • cte 代表什么?
      • @vy32:CTE 代表“公用表表达式”。
      【解决方案4】:

      只需将计算放在GROUP BY 子句中:

      替换

      group by mwspp.DateDue
      

      group by dateadd(day, -7, Convert(DateTime, mwspp.DateDue) + (7 - datepart(weekday, mwspp.DateDue)))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-09-27
        • 1970-01-01
        • 1970-01-01
        • 2012-12-31
        • 1970-01-01
        • 2019-04-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多