是否有一个已建立的SQL查询模式,它按范围分组?

Wid*_*dor 9 sql sql-server design-patterns group-by

关于如何通过SQL查询中的范围对数据进行分组,我已经看到了很多关于SO 的问题.

具体情况各不相同,但每个方面的一般基本问题是按一系列值而不是GROUP BY列中的每个离散值进行分组.换句话说,要按照比存储在数据库表中更精确的粒度进行分组.

在生成直方图,日历表示,数据透视表和其他定制报告输出等内容时,这通常会在现实世界中出现.

一些示例数据(表格无关):

|      OrderHistory       |       |         Staff        |                
---------------------------       ------------------------
|    Date    |  Quantity  |       |   Age     |   Name   |
---------------------------       ------------------------       
|01-Jul-2012 |     2      |       |    19     |   Barry  |
|02-Jul-2012 |     5      |       |    53     |   Nigel  |
|08-Jul-2012 |     1      |       |    29     |   Donna  |
|10-Jul-2012 |     3      |       |    26     |   James  |
|14-Jul-2012 |     4      |       |    44     |   Helen  |
|17-Jul-2012 |     2      |       |    49     |   Wendy  |
|28-Jul-2012 |     6      |       |    62     |   Terry  |
---------------------------       ------------------------
Run Code Online (Sandbox Code Playgroud)

现在假设我们想要使用表格的DateOrderHistory按周分组,即7天范围.或者可能将其Staff划分为10年的年龄范围:

|       Week      |  QtyCount  |        |  AgeGroup | NameCount |         
--------------------------------        -------------------------
|01-Jul to 07-Jul |     7      |        |   10-19   |    1      |
|08-Jul to 14-Jul |     8      |        |   20-29   |    2      | 
|15-Jul to 21-Jul |     2      |        |   30-39   |    0      |
|22-Jul to 28-Jul |     6      |        |   40-49   |    2      |
--------------------------------        |   50-59   |    1      |
                                        |   60-69   |    1      |
                                        -------------------------
Run Code Online (Sandbox Code Playgroud)

GROUP BY Date并且GROUP BY Age他们自己也不会这样做.

我看到的最常见的答案(其中没有一个被一致投票"正确")是使用以下一个或多个:

  • 一堆CASE语句,每个分组一个
  • 一堆UNION查询,WHERE每个分组都有一个不同的子句
  • 因为我正在使用SQL Server,PIVOT()UNPIVOT()
  • 使用子选择,临时表或视图构造的两阶段查询

是否存在用于处理此类查询的已建立的通用模式?

Noa*_*oah 1

难道您不能将年龄(或日期)视为一个新的、只有年龄(或日期)及其相应范围的小表中的外键吗?连接语句可以提供一个新表,其中的列包含 AgeGroups。对于新表,您可以使用标准的分组方法。

创建一个新表进行分组似乎确实很鲁莽,但以编程方式制作很容易,而且我认为它比 case 语句或 where 子句更容易维护(或删除并重新创建)。如果这个查询的结果是一次性的,那么一次性的 sql 语句可能效果最好,但我认为我的方法对于长期使用最有意义。