【问题标题】:How to use a CASE statement within a SELECT COUNT statement?如何在 SELECT COUNT 语句中使用 CASE 语句?
【发布时间】:2016-12-20 11:02:04
【问题描述】:

我需要做一个案例陈述。

根据变量值是什么,需要从表中选择正确的列

StartDate 和 EndDate 是不同的变量。

我创建了一个名为 Region 的变量,它应该确定查询选择的列。

编辑:地区可以是英格兰和威尔士的“EW”,苏格兰的“SC”或北爱尔兰的“NI”。 如果是 EW,则应选择第 1 列,第 2 列选择 SC,第 3 列选择 NI

SELECT
COUNT(COLUMN1)
FROM  bankholidays
WHERE COLUMN1 BETWEEN @StartDate AND @EndDate)

【问题讨论】:

  • 也就是说,你想动态选择列?
  • 请提供样本数据和预期数据
  • 你指望的栏目重要吗?即是否有您关心的空值,或者count(*)count(1)(功能相同)可以吗?或者,是您感兴趣的 WHERE 语句中的列吗?

标签: sql-server tsql count case


【解决方案1】:

假设您要计算 Column1 在开始日期和结束日期之间的记录数,那么以下应该可以工作:

SELECT SUM(CASE WHEN COLUMN1 BETWEEN @StartDate AND @EndDate
           THEN 1 ELSE 0 END) AS tally
FROM bankholidays

这种方法称为条件聚合,通常您还会使用GROUP BY 子句。

更新:

要处理您的 @Region 变量,查询可能如下所示:

SELECT CASE WHEN @Region = 'val1' THEN COLUMN1
            WHEN @Region = 'val2' THEN COLUMN2
            WHEN @Region = 'val3' THEN COLUMN3
       END AS new_column   
FROM bankholidays

请注意,我没有尝试将它与第一个查询结合起来,因为它会将聚合函数与非聚合项混合在一起,这可能没有意义。

【讨论】:

  • 我的另一个变量是@Region,它可以包含3个不同的值。我如何使用它来选择第 1 列、第 2 列或第 3 列?
【解决方案2】:
SELECT CASE
WHEN @Region = 'EW' THEN columnName
WHEN @Region = 'SC' THEN columnName
WHEN @Region = 'NI' THEN columnName
END AS newColumnName FROM bankholidaysT

试试这样的

【讨论】:

    【解决方案3】:

    1) 如果您不关心从计数中排除空值,则无需在 COUNT 语句中指定列名。即

    select count(Column1)
    

    将给出与

    相同的结果
    select count(1)
    

    或者

    select count(*)
    

    只要 column1 没有空值。如果 column1 确实包含空值,则不计算在内(因此,如果有 10 条记录,其中 3 条在 column1 中有空值,则使用 count(column1) 会得到 7 的结果,使用其他方法会得到 10 的结果。

    我首先提到这一点,好像您关心空值然后更改此处使用的列是有意义的;如果不这样做,请使用 count(1) / counnt(*) 的更简单逻辑。

    说了这么多,以下是更改该列的方法:

    select count(
        case @Region 
            when 1 then Column1 
            when 2 then Column2 
            else Column3 
        end
    )
    

    2) 如果要更改 WHERE 语句中使用的列,有几种方法:

    SELECT COUNT(1)
    FROM  bankholidays
    WHERE case @Region 
        when 1 then Column1 
        when 2 then Column2 
        else Column3        
    end BETWEEN @StartDate AND @EndDate
    

    SELECT COUNT(1)
    FROM  bankholidays
    WHERE (@Region = 1 and Column1 BETWEEN @StartDate AND @EndDate)
    or (@Region = 2 and Column2 BETWEEN @StartDate AND @EndDate
    or (@Region not in (1,2) and Column3 BETWEEN @StartDate AND @EndDate
    

    我个人更喜欢上面的第一种风格,因为它涉及的重复较少;但是第二种样式提供了为不同的列使用不同的开始和结束日期的选项,或者也可以添加其他逻辑,因此仍然值得注意。

    【讨论】:

    • 如果您对count(1)count(*) 的文章感兴趣,可以在这里讨论:stackoverflow.com/questions/1221559/count-vs-count1Count(*) 更常见,但我更喜欢count(1),因为我觉得它更有意义,也更符合其他聚合运算符(例如sum(1)
    【解决方案4】:

    如果要动态计算给定列值介于两个日期之间的记录,请使用动态查询:

    DECLARE @column NVARCHAR(MAX)
    DECLARE @sql NVARCHAR(MAX)
    
    SET @column = 'COLUMN1' --Set your desired column here
    SET @sql = 'SELECT COUNT(*) FROM bankholidays WHERE ' + @column + ' BETWEEN ''' + CONVERT(NVARCHAR,@StartDate,121) + ''' AND ''' + CONVERT(NVARCHAR,@EndDate,121) + ''''
    
    EXEC @sql
    

    【讨论】:

    • 我只建议将动态 sql 作为最后的手段,尤其是在将其编写为存储过程或将来可能维护的查询时。顺便说一句,它还不错。
    • 我不是说你错了,而是出于兴趣——为什么?
    • 因为它很难维护,尤其是当查询随时间增长时。我做过一些不需要存在的动态 SQL 的噩梦。当您有长对象名称或不记得哪个参数在函数中的位置时,您也不会获得智能感知。谁愿意花 15-20 分钟来解开有时动态的混乱,只是为了稍微改变一下连接?如果你可以不做,那就不做。将动态 SQL 构建留给 ORM 或使用同义词或只是……一些东西。
    【解决方案5】:

    试试这个如果你想count并动态检查列

    DECLARE @sql VARCHAR(500), 
        @Region VARCHAR(100) = 'COLUMN2', --It can be Column1, Column2.....
        @StartDate DATETIME = '2016-04-10',
        @EndDate DATETIME = '2016-04-15'
    
    SET @sql = '
        SELECT
        COUNT(' + @Region + ')
        FROM  bankholidays
        WHERE ' + @Region + ' BETWEEN ''' + CAST(@StartDate AS VARCHAR) + ''' AND ''' + CAST(@EndDate AS VARCHAR) + ''''
    
    EXEC (@SQL)
    

    --查询执行如下

    SELECT
    COUNT(COLUMN2)--It can be Column1, Column2.....
    FROM  bankholidays
    WHERE COLUMN2 BETWEEN 'Apr 10 2016 12:00AM' AND 'Apr 15 2016 12:00AM'
    

    【讨论】:

      【解决方案6】:
      declare  @Region  varchar(10)
      set @Region='EW'
      
      SELECT 
      COUNT(*) OVER(PARTITION BY 1) as TotalRows,
      Case  
          when @Region ='EW' THEN   Column1 
          when @Region ='SC' THEN   Column2
          when @Region ='NI' THEN   Column3
      end as [NewColumn]
      FROM [BankHolidays] 
      WHERE COLUMN1 BETWEEN @StartDate AND @EndDate
      

      【讨论】:

      • 我认为这个问题还需要根据@Region的值动态指定WHERE子句中的列。
      猜你喜欢
      • 1970-01-01
      • 2014-02-08
      • 2023-04-07
      • 1970-01-01
      • 1970-01-01
      • 2016-05-02
      • 2014-12-05
      • 2023-03-18
      • 1970-01-01
      相关资源
      最近更新 更多