【问题标题】:Create enumeration and use it in aggregate function创建枚举并在聚合函数中使用它
【发布时间】:2014-08-13 13:38:58
【问题描述】:

是否可以在下面的语句中为'a','b','test','123','blabla' 创建一些枚举?

sum(case when col1 in ('a','b','test','123','blabla') then col2 end) as sum

我尝试从letters_table 读取它,如下所示:

sum(case when col1 in (select letter from letters_table) then col2 end) as sum

但它告诉我Cannot perform an aggregate function on an expression containing an aggregate or a subquery.

以下对我来说效果不佳:

DECLARE @letters varchar(10)
select @letters = letter FROM letters_table
sum(case when col1 in (@letters) then col2 end) as sum

因为当我打印@letters 时,只有最后一个'blabla'

【问题讨论】:

  • Sum 是一个数学函数,不适用于文本。也许你想使用一个字符串...我相信SQL服务器使用STUFF。但可能需要与 FOR XML Path 一起使用来聚合行。
  • 从您的代码中不清楚您要做什么。你指的 col1 和 col2 是什么?你想得到多少金额?
  • @xQbert: 不仅仅适用于这个例子,它可以是任何字符串,不仅仅是 a、b、c、d,而是例如测试、树、心、123等

标签: sql sql-server


【解决方案1】:

如果表中有 col1(文本列)和 col2(数字列),例如 myTable,另一个表中有字母(文本列),例如 letters_table,那么您可以使用 JOIN,如下:

SELECT 
    --mt.col1,        Include for totals by col1
    SUM(mt.col2)
FROM myTable mt
INNER JOIN letters_table lt
ON mt.col1 = lt.letter;
--    GROUP BY mt.col1    Include for totals by col1
--    ORDER BY mt.col1;   Include for totals by col1

【讨论】:

  • 这将为每个单词返回单独的行,我相信这不是 OP 所要求的(基于他的 cmets 和 related question
  • @kristof 我修改了查询以获得一个总数。此查询应该更快,因为它使用 JOIN。
【解决方案2】:

您使用子查询的第二个示例可能是最好的 - 您只需在两个单独的阶段执行子查询和聚合,如下所示:

select sum(x.col2) as sum
from (
    select case 
           when col1 in (select letter from letters_table) then col2 
           else 0 
           end as col2
    from YourTableName
) x

这应该可以按预期工作,并使解析器满意。

【讨论】:

    【解决方案3】:

    ...或者您可以使用公用表表达式,例如:

    DECLARE @Test TABLE (col1 VARCHAR(1), col2 INT);
    INSERT INTO @Test VALUES ('a', 1);
    INSERT INTO @Test VALUES ('c', 20);
    INSERT INTO @Test VALUES ('z', 3);
    DECLARE @Letters TABLE (Letter VARCHAR(1));
    INSERT INTO @Letters VALUES ('a');
    INSERT INTO @Letters VALUES ('b');
    INSERT INTO @Letters VALUES ('c');
    WITH PreQuery AS (
        SELECT
            col1,
            CASE WHEN l.Letter IS NULL THEN 0 ELSE 1 END AS GoodLetter,
            col2
        FROM
            @Test t
            LEFT JOIN @Letters l ON l.Letter = t.col1)
    SELECT 
        SUM(CASE WHEN GoodLetter = 1 THEN col2 END) 
    FROM 
        PreQuery;
    

    【讨论】:

      【解决方案4】:

      solution posted by Richard 应该可以解决问题,但不需要使用 cte 你可以简单地使用下面的代码

      select
         isnull(sum(mt.col2),0)
      from 
        myTbl mt
        inner join lettersTbl lt
          on mt.col1 = lt.letter
      

      如果您想包含结果中涉及的字母,您可以使用变量。查看your previous post 这里的代码与您提供的示例数据相同

      declare @yourTbl table (col1 char(1), col2 int);
      insert into @yourTbl values ('a', 10)
      ,('b', 5)
      ,('c', 15)
      ,('d', 2)
      ,('a', 3)
      ,('b', 6) 
      ,('c', 8) 
      ,('d', 10);
      
      declare @lettersTbl table (letter char(1));
      -- insert your letters here
      insert into @lettersTbl values ('a'),('b')
      
      
      -- only needed if you want to display the letters involved too
      declare @checkedLetters as varchar(50)
      select @checkedLetters = concat(@checkedletters,lt.letter)
      from 
          @letterstbl lt
      
      select
          @checkedletters 
         ,isnull(sum(mt.col2),0)
      from 
          @yourtbl mt
          inner join @letterstbl lt
            on mt.col1 = lt.letter
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-06
        • 1970-01-01
        相关资源
        最近更新 更多