【问题标题】:Split the semicolon separated values into many columns and assign boolean 1 to the columns if the value matches to the column name else assign 0将分号分隔的值拆分为多列,如果值与列名匹配,则将布尔值 1 分配给列,否则分配 0
【发布时间】:2020-03-04 12:32:10
【问题描述】:

我的数据以分号分隔的值存在于一个名为“主列”的列中,如下所示,最多有 12 个唯一值,我想将这些值拆分为 12 个单独的列,如 bv、fv、iv 等这些单独的列应填充为 1(如果它与主列值匹配),否则为 0(如果与主列值不匹配)。

主列数据

例如,

如果主列有数据

bv;fv;iv;kv;lr;lv;lz;mv;sh;sv;sz;wv;

那么所有 12 个单独的列都应该填充 1。

如果主列有数据 bv;fv;iv;那么只有三个单独的列(bv、fv、iv)的布尔值应该是 1,其他列的值应该是 0。

等等。

请你帮我写一个快速的 SQL 语句来实现上述要求?

【问题讨论】:

  • 请标上您真正使用的数据库。
  • 由于没有其他人提到它,您应该考虑在这里修复数据模型。存储带分隔符的值违反了 1NF,而且使用起来会更加麻烦和缓慢。

标签: sql sql-server sql-server-2016


【解决方案1】:

您可以使用case 表达式。在SELECT 中,这将是:

select (case when col like '%bv%' then 1 else 0 end) as bv,
       (case when col like '%fv%' then 1 else 0 end) as fv,
       . . . 

上面的工作假设“代码”总是两个字符。

或者如果代码可以是可变长度的,请考虑分隔符:

select (case when ';' + col + ';' like '%;bv;%' then 1 else 0 end) as bv,
       (case when ';' + col + ';' like '%;fv;%' then 1 else 0 end) as fv,
       . . . 

这也可以很容易地合并到update 中。

【讨论】:

  • 谢谢 Gordon,简单的案例可以满足我的要求。
【解决方案2】:

作为替代方法,也可以使用STRING_SPLIT 对数据进行规范化,然后使用条件聚合(也称为交叉表)对其进行透视:

SELECT MAX(CASE WHEN SS.item = 'bv' THEN 1 ELSE 0 END AS bv,
       MAX(CASE WHEN SS.item = 'fv' THEN 1 ELSE 0 END AS fv,
       ...
       MAX(CASE WHEN SS.item = 'wv' THEN 1 ELSE 0 END AS wv
FROM dbo.YourTable YT
     CROSS APPLY STRING_SPLIT(YT.YourColumn,';') SS;

不过,我个人建议修复您的设计并对其进行规范化。

【讨论】:

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