【问题标题】:Flattening T-SQL bitmask from enumeration table从枚举表中展平 T-SQL 位掩码
【发布时间】:2016-08-13 08:11:07
【问题描述】:

我正在尝试展平存储在位掩码中的函数列表,并在这样的枚举表中“解释”:

CREATE TABLE #enum([ID] [int] NOT NULL IDENTITY(1, 1) PRIMARY KEY,
                   [Display] [varchar] (50) NOT NULL,
                   [DataValue] [int] NOT NULL);

INSERT INTO [#enum] ([Display], [DataValue]) 
SELECT  'Function A', 1 
UNION SELECT 'Function B', 2 
UNION SELECT 'Function C', 4 
UNION SELECT 'Function D', 8 
UNION SELECT 'Function E', 16
UNION SELECT 'Function F', 32 
UNION SELECT 'Function G', 64;

我的数据表看起来像这样(显然简化了很多):

CREATE TABLE #people ([ID] [int] NOT NULL IDENTITY(1, 1) PRIMARY KEY,
                      [PersonName] [varchar] (50) NOT NULL,
                      [Functions] [int] NOT NULL);

INSERT INTO [#people] ([PersonName], [Functions]) 
SELECT'Ken Hurt', 8 
UNION SELECT 'Justin Case', 33 
UNION SELECT 'Bill Board', 73;

现在我想在查询#people 表时返回一个以逗号分隔的函数列表;结果如下:

ID        Name          Functions
1         Ken Hurt      Function D
2         Justin Case   Function A, Function F
3         Bill Board    Function A, Function D, Function G

我一直在研究动态 SQL、PIVOTSTUFF()FOR XML PATH() 已经有一段时间了,但我显然太愚蠢了,无法消化这个美丽的概念。能否请你帮忙?使用 WHILE 甚至更糟的光标浏览列表似乎就像用大锤敲击坚果一样。谢谢!

【问题讨论】:

  • 你为什么选择违反第一范式来处理这种多对多关系?
  • 不是我 - C# 开发人员显然喜欢使用位掩码
  • 返回一个规范化的结果集,让 C# 开发人员按照他们想要的方式对其进行格式化。
  • @JeroenMostert 抱歉,我已经编辑了帖子

标签: sql sql-server tsql pivot


【解决方案1】:

正确方法:

架构已“损坏”。规范化它。


解决方法:

不需要WHILE/CURSOR/PIVOT/Dynamic-SQL。简单的按位运算就可以完成这项工作:

SELECT *
FROM #people p
CROSS APPLY(SELECT STUFF((SELECT ',' + e.Display
                          FROM #enum e
                          WHERE p.Functions & DataValue = DataValue
                          ORDER BY e.DataValue
                          FOR XML PATH('')), 1, 1, '')
           ) AS sub(result);

LiveDemo

输出:

╔════╦═════════════╦═══════════╦══════════════════════════════════╗
║ ID ║ PersonName  ║ Functions ║              result              ║
╠════╬═════════════╬═══════════╬══════════════════════════════════╣
║  1 ║ Bill Board  ║        73 ║ Function A,Function D,Function G ║
║  2 ║ Justin Case ║        33 ║ Function A,Function F            ║
║  3 ║ Ken Hurt    ║         8 ║ Function D                       ║
╚════╩═════════════╩═══════════╩══════════════════════════════════╝

【讨论】:

  • 这看起来像是我愚蠢的解决方案!我将在实时数据上对其进行测试并接受。谢谢!
  • 另一种对我来说似乎更简单的解决方案:stackoverflow.com/a/16404032/749626
【解决方案2】:

我像这样解决了我非常相似的问题:

  SELECT p.nmbCurrentLivingSituation,
    SUBSTRING(
            CASE WHEN p.nmbCurrentLivingSituation & POWER(2,0) = POWER(2,0) THEN ', Two Parent Family' ELSE '' END
          + CASE WHEN p.nmbCurrentLivingSituation & POWER(2,1) = POWER(2,1) THEN ', One Parent Family' ELSE '' END
          + CASE WHEN p.nmbCurrentLivingSituation & POWER(2,2) = POWER(2,2) THEN ', Foster' ELSE '' END
          + CASE WHEN p.nmbCurrentLivingSituation & POWER(2,3) = POWER(2,3) THEN ', Step Home' ELSE '' END
          + CASE WHEN p.nmbCurrentLivingSituation & POWER(2,4) = POWER(2,4) THEN ', Institution' ELSE '' END
          + CASE WHEN p.nmbCurrentLivingSituation & POWER(2,5) = POWER(2,5) THEN ', Living On Own' ELSE '' END
          + CASE WHEN p.nmbCurrentLivingSituation & POWER(2,6) = POWER(2,6) THEN ', Homeless' ELSE '' END
          + CASE WHEN p.nmbCurrentLivingSituation & POWER(2,7) = POWER(2,7) THEN ', Other' ELSE '' END
          + CASE WHEN p.nmbCurrentLivingSituation & POWER(2,8) = POWER(2,8) THEN ', Siblings' ELSE '' END
          + CASE WHEN p.nmbCurrentLivingSituation & POWER(2,9) = POWER(2,9) THEN ', Relatives' ELSE '' END
          + CASE WHEN p.nmbCurrentLivingSituation & POWER(2,10) = POWER(2,10) THEN ', Spouse' ELSE '' END
          + CASE WHEN p.nmbCurrentLivingSituation & POWER(2,11) = POWER(2,11) THEN ', Non-Marital Partner Childs Parent' ELSE '' END
          + CASE WHEN p.nmbCurrentLivingSituation & POWER(2,12) = POWER(2,12) THEN ', Non-Marital Partner not Childs Parent' ELSE '' END
          + CASE WHEN p.nmbCurrentLivingSituation & POWER(2,13) = POWER(2,13) THEN ', Unknown' ELSE '' END
        , 3, 150) As [values]
    FROM tblParticipant p

结果如下所示:

nmbCurrentLivingSituation   values
1       Two Parent Family
2       One Parent Family
NULL
0
770     One Parent Family, Siblings, Relatives

感谢这篇文章: In SQL, how can I split the values in a bitmask total into a comma delimited string

【讨论】:

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