【问题标题】:Lots of WHEN conditions in CASE statement (binning)CASE 语句中的大量 WHEN 条件(分箱)
【发布时间】:2016-03-12 01:03:40
【问题描述】:

如果我需要大约 100 个 bin,如何在 SQL Server 2008 中进行 binning?我需要根据分箱变量是否属于 100 个相等间隔之一来对记录进行分组。 例如,如果有连续的变量年龄,我可以写:

CASE
   WHEN AGE >= 0 AND AGE < 1 THEN '1'
   WHEN AGE >= 1 AND AGE < 2 THEN '2'
   ...
   WHEN AGE >= 99 AND AGE < 100 THEN '100'
END [age_group]

但是这个过程会很耗时吗?还有其他方法可以做到这一点吗?

【问题讨论】:

  • 好吧-从您的示例中,您似乎实际上并不需要 CASE,因为 0 岁返回 1 并且 1 岁返回 2 等等....?所以看起来age_group 只是Age + 1?
  • @AllanS.Hansen,这取决于AGE 的数据类型(尽管int 以外的任何数据类型都会很奇怪)
  • @HoneyBadger 确实,使用不同的数据类型似乎可以进行演员表。
  • 案例表达,不是案例陈述。 (case 表达式返回一个值。)
  • 嗯,您可以随时将其与包含您的价格段的表格结合使用。您在关系数据库中,使用关联

标签: sql sql-server sql-server-2008 tsql case


【解决方案1】:

我猜是数学。在这种情况下,

Ceiling(Age) AS [age_group]

根据需要转换为您选择的字符类型。 Ceiling 是 SQL Server 中的“向上取整”函数。

【讨论】:

  • Age 为零时,返回 0,但 OP 需要 '1' ??
【解决方案2】:

您可以为此目的使用算术。像这样的:

select floor(bins * (age - minage) / (range + 1)), count(*)
from t cross join
     (select min(age) as minage, max(age) as maxage,
             1.0*(max(age) - min(age)) as range, 100 as bins
      from t
     ) m
group by floor(bins * (age - minage) / (range + 1))

但是,这对于您的示例来说太过分了,根本不需要 case

【讨论】:

  • 您的回答实际上使我找到了解决方案。谢谢
【解决方案3】:

尝试此代码一次:

SELECT CASE
         WHEN AGE = 0 THEN 1
         ELSE Ceiling([age])
       END [age_group]
FROM   @T 

这里的CEILING函数返回大于或等于指定数值表达式的最小整数。即select CEILING(0.1) SQL Returns 1 As Output

但是根据你的输出要求 Floor(age)+1 就足够得到Required Output了。

SELECT Floor([age]) + 1 [age_group]
    FROM   @T 

Here Floor Function 返回小于或等于指定数值表达式的最大整数。

【讨论】:

  • @Allan S. Hansen 是的 FLOOR(age)+1 也可以。但是为什么我们需要再次 +1 来自那个 FLOOR 函数而不是那个 CEILING 返回直接答案。
  • 同意@AllanS.Hansen;因为条件 1 &lt;= x &lt; 2 给出 2 你需要他的版本。 Ajay 的版本在1 &lt; x &lt;= 2 条件下效果最好(这是更常见的情况)。这也减少了对 case 语句的需求(除非您还希望检查 x &lt; 0x &gt;= 100 以进行异常处理)。
  • 但是 OP 希望 1 返回 2。这不是
  • @Frisbee 是 Ceiling 在这种情况下不产生所需的输出,但 Floor(age)+1 产生所需的输出。
【解决方案4】:

如果您的组间隔是固定的 - 例如 1200,您只需进行整数除法即可获得该分组的索引。

例如:

SELECT 1000 / 1200 等于 0
SELECT 2200 / 1200 等于 1
请记住 - 如果您使用的是十进制数据类型,则需要强制转换为 int 才能获得结果。整数除法需要运算符两边都是 int。

然后加1得到组

【讨论】:

    【解决方案5】:

    根据您对分段为 1200 的评论尝试此操作:

    ;With Number
    AS
    (
        SELECT * 
        FROM (Values(1),(2), (3), (4), (5), (6), (7), (8), (9), (10))N(x)
    ),
    Segments
    As
    ( 
        SELECT (ROW_NUMBER() OVER(ORDER BY Num1.x) -1) * 1200 As StartNum,
               ROW_NUMBER() OVER(ORDER BY Num1.x)  * 1200 As EndNum 
        FROM Number Num1
        CROSS APPLY Number Num2
    )
    SELECT *
    FROM Segments
        SELECT *
        FROM Segments
        INNER JOIN MyTable
           ON MyTable.Price >= StartNum AND MyTable.Price < EndNum
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-10
      • 2016-07-08
      相关资源
      最近更新 更多