【问题标题】:How to group by an expression in TSQL and capture the result?如何按 SQL 中的表达式分组并捕获结果?
【发布时间】:2018-03-26 03:03:35
【问题描述】:

如何在 GROUP BY 子句中包含表达式的结果并选择表达式的输出?

假设我有这张桌子:

╔════════════════════════╦═══════════╦═══════╗
║         Forest         ║  Animal   ║ Count ║
╠════════════════════════╬═══════════╬═══════╣
║ Tongass                ║ Hyena     ║   600 ║
║ Tongass                ║ Bear      ║  1200 ║
║ Mount Baker-Snoqualmie ║ Wolf      ║    30 ║
║ Mount Baker-Snoqualmie ║ Bunny     ║     2 ║
║ Ozark-St. Francis      ║ Pigeon    ║   100 ║
║ Ozark-St. Francis      ║ Ostrich   ║     1 ║
║ Bitterroot             ║ Tarantula ║  9001 ║
╚════════════════════════╩═══════════╩═══════╝

我需要一行记录每个森林中食肉动物的数量,并记录一排非食肉动物的数量(如果有的话)。这是我在这个例子中寻找的输出:

╔════════════════════════╦═══════════════╦═══════════════╗
║         Forest         ║ AnimalsOfType ║ AreCarnivores ║
╠════════════════════════╬═══════════════╬═══════════════╣
║ Tongass                ║          1800 ║             1 ║
║ Mount Baker-Snoqualmie ║             2 ║             0 ║
║ Mount Baker-Snoqualmie ║            30 ║             1 ║
║ Ozark-St. Francis      ║           101 ║             0 ║
║ Bitterroot             ║          9001 ║             1 ║
╚════════════════════════╩═══════════════╩═══════════════╝

动物是否是肉食性的信息被编码在表达式中。

我想做的是在 group-by 中包含表达式并在 select 子句中引用它的结果:

SELECT TOP (1000)
    [Forest],
    SUM([COUNT]) AS AnimalsOfType,
    AreCarnivores
FROM [Tinker].[dbo].[ForestAnimals]
GROUP BY
    Forest,
    CASE WHEN ForestAnimals.Animal IN ('Pigeon', 'Ostrich', 'Bunny') THEN 0 ELSE 1 END AS AreCarnivores

但是,这不是有效的 TSQL 语法。

如果我在 GROUP BY 子句中包含 Animal 列以允许我在 SELECT 中重新运行该函数,我将得到每种动物类型的一行,这不是所需的行为。

对临时表进行单独选择并将结果合并是不可取的,因为此查询的实际版本具有大量表达式,需要在同一结果集中进行此行为,这将导致非常尴尬的存储过程。

【问题讨论】:

  • 你能展示一下这个功能吗?我们需要查看输入和输出。
  • 我认为“功能”在这里是一个红鲱鱼;他需要一个表达式,它可能是也可能不是 UDF。
  • 为格式精美的表格点赞!

标签: sql tsql sql-server-2012 group-by


【解决方案1】:

使用 CTE:

WITH X AS (
  SELECT Forest, Animal, Count,
         CASE WHEN ForestAnimals.Animal IN ('Pigeon', 'Ostrich', 'Bunny') 
              THEN 0 
              ELSE 1 END AS AreCarnivores
  FROM [Tinker].[dbo].[ForestAnimals]
)
SELECT Forest, SUM(Count) AS AnimalsOfType, AreCarnivores
FROM X
Group by Forest, AreCarnivores;

或者更详细地重复一遍:

SELECT   Forest, SUM(Count) AS AnimalsOfType, 
         CASE WHEN ForestAnimals.Animal IN ('Pigeon', 'Ostrich', 'Bunny') 
              THEN 0 
              ELSE 1 END AS AreCarnivores
FROM [Tinker].[dbo].[ForestAnimals]
GROUP BY Forest, CASE WHEN ForestAnimals.Animal IN ('Pigeon', 'Ostrich', 'Bunny') 
                 THEN 0 
                 ELSE 1 END;

它们是优化器的等效查询。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-03
    相关资源
    最近更新 更多