从枚举 table 中展平 T-SQL 位掩码
Flattening T-SQL bitmask from enumeration table
我正在尝试展平存储在位掩码中的函数列表,这些函数在枚举 table 中 "explained" 如下所示:
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;
我的数据 table 看起来像这样(显然简化了很多):
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;
现在我想 return 在查询 #people table 时使用逗号分隔的函数列表;结果是这样的:
ID Name Functions
1 Ken Hurt Function D
2 Justin Case Function A, Function F
3 Bill Board Function A, Function D, Function G
我已经关注 Dynamic SQL、PIVOT
、STUFF()
和 FOR XML PATH()
有一段时间了,但我显然太笨了,无法消化美丽的概念。能否请你帮忙?使用 WHILE 或更糟的 Cursors 浏览列表就像用大锤敲碎坚果一样。谢谢!
正确方法:
架构是 "broken"。归一化。
解决方法:
不需要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);
输出:
╔════╦═════════════╦═══════════╦══════════════════════════════════╗
║ 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 ║
╚════╩═════════════╩═══════════╩══════════════════════════════════╝
我这样解决了我非常相似的问题:
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
我要感谢这个post:
In SQL, how can I split the values in a bitmask total into a comma delimited string
我正在尝试展平存储在位掩码中的函数列表,这些函数在枚举 table 中 "explained" 如下所示:
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;
我的数据 table 看起来像这样(显然简化了很多):
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;
现在我想 return 在查询 #people table 时使用逗号分隔的函数列表;结果是这样的:
ID Name Functions
1 Ken Hurt Function D
2 Justin Case Function A, Function F
3 Bill Board Function A, Function D, Function G
我已经关注 Dynamic SQL、PIVOT
、STUFF()
和 FOR XML PATH()
有一段时间了,但我显然太笨了,无法消化美丽的概念。能否请你帮忙?使用 WHILE 或更糟的 Cursors 浏览列表就像用大锤敲碎坚果一样。谢谢!
正确方法:
架构是 "broken"。归一化。
解决方法:
不需要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);
输出:
╔════╦═════════════╦═══════════╦══════════════════════════════════╗
║ 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 ║
╚════╩═════════════╩═══════════╩══════════════════════════════════╝
我这样解决了我非常相似的问题:
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
我要感谢这个post: In SQL, how can I split the values in a bitmask total into a comma delimited string