具有表格的形式
pk items
--------
1 a,b,c,...
2 d,e,f,...
3 g,h,i,...
4 j,k,l,...
.
.
.
商品列的值是可变长度的csv字符串(其元素不必是唯一的),例如杂货(仅在此处使用字母以提高可读性)。
因此,希望能够生成一个二进制矩阵来表示任何给定pk所包含的项目,例如。
pk a b c d e f g ...
--------------------
1 1 1 1 0 0 0 0 ...
2 0 0 0 1 1 1 0 ...
3 0 0 0 0 0 0 0 ...
.
.
.
请注意,我还可以访问一个表,该表代表csv列表中任何项目的可能值的整个域,例如。
item
------
a
b
c
.
.
.
有人知道这样做的有效方法吗?
答案 0 :(得分:2)
我完全同意所作的评论,这与存储数据的理想方式相去甚远。您的表Form
应该被规范化,实际上您应该使用表示层来做到这一点。我已经使用STRING_SPLIT
编写了以下内容,但是,您也可以使用DelimitedSplit8k_LEAD
来实现此目的。 (更正后,在使用SQL Server 2012时,您将需要这样做。)
这不是入门级的东西,所以请问您是否不了解:
--Create the table with all the items
CREATE TABLE dbo.Item (ItemID int IDENTITY (1,1),
ItemName varchar(2));
INSERT INTO dbo.Item(ItemName)
VALUES('a'),
('b'),
('c'),
('d'),
('e'),
('f'),
('g'),
('h'),
('i'),
('j'),
('k'),
('l'),
('m'),
('n'),
('o'),
('p'),
('q');
GO
--And now your sample data
CREATE TABLE dbo.Form (Pk int IDENTITY (1,1),
Items varchar(100)); --Really you shouldn't be storing delimited data
INSERT INTO dbo.Form (Items)
VALUES ('a,b,c'),
('d,e,f'),
('g,h,i'),
('j,k,l');
GO
--Declare the SQL variable to store the dynamic SQL
DECLARE @SQL nvarchar(MAX);
--Build the SQL. Use FOR XML PATH to create the delimited list of columns,
--STRING_SPLIT in the dynamic SQL to split the data
--and a cross tab to pivot the data
--YUCK (sorry)
SET @SQL = N'SELECT F.Pk,' + NCHAR(13) + NCHAR(10) +
STUFF((SELECT N',' + NCHAR(13) + NCHAR(10) +
N' CASE WHEN COUNT(CASE WHEN SS.[value] = ' + QUOTENAME(I.ItemName,'''') + N'THEN 1 END) = 0 THEN 0 ELSE 1 END AS ' + QUOTENAME(I.ItemName)
FROM dbo.Item I
ORDER BY I.ItemName ASC
FOR XML PATH(N''),TYPE).value('.','nvarchar(MAX)'),1,3,N'') + NCHAR(13) + NCHAR(10) +
N'FROM dbo.Form F' + NCHAR(13) + NCHAR(10) +
N' CROSS APPLY STRING_SPLIT(F.Items,'','') SS' + NCHAR(13) + NCHAR(10) +
N'GROUP BY Pk;';
PRINT @SQL; --Your best friend for debugging
EXEC sp_executesql @SQL;
GO
DROP TABLE dbo.Form;
DROP TABLE dbo.Item;