我有这个奇怪的场景(至少对我而言)我有一个表(实际上是一个结果集,但我想让它更简单),如下所示:
ID | Actions
------------------
1 | 10,12,15
2 | 11,12,13
3 | 15
4 | 14,15,16,17
我想计算所有表中的不同动作。在这种情况下,我希望结果为8(只计算10,11,....,17;并忽略重复的值)。
如果重要,我使用的是MS SQL 2008。
如果它变得更容易,那么之前的操作就像XML一样
<root>
<actions>10,12,15</actions>
</root>
我怀疑它会让它变得更容易,但是有些人可能会回来使用我不知道的xml函数,只是让一切变得更容易。
请告诉我是否还有其他问题。
答案 0 :(得分:1)
使用与http://codecorner.galanter.net/2012/04/25/t-sql-string-deaggregate-split-ungroup-in-sql-server/类似的方法:
首先你需要一个能够分割字符串的函数,SO上有很多例子,这里有一个例子:
CREATE FUNCTION dbo.Split (@sep char(1), @s varchar(512))
RETURNS table
AS
RETURN (
WITH Pieces(pn, start, stop) AS (
SELECT 1, 1, CHARINDEX(@sep, @s)
UNION ALL
SELECT pn + 1, stop + 1, CHARINDEX(@sep, @s, stop + 1)
FROM Pieces
WHERE stop > 0
)
SELECT pn,
SUBSTRING(@s, start, CASE WHEN stop > 0 THEN stop-start ELSE 512 END) AS s
FROM Pieces
)
使用此功能,您可以运行简单的查询:
SELECT COUNT(DISTINCT S) FROM MyTable CROSS APPLY dbo.Split(',', Actions)
答案 1 :(得分:1)
MS SQL Server 2008架构设置:
CREATE TABLE Table1
([ID] int, [Actions] varchar(11))
;
INSERT INTO Table1
([ID], [Actions])
VALUES
(1, '10,12,15'),
(2, '11,12,13'),
(3, '15'),
(4, '14,15,16,17')
;
查询1 :
DECLARE @S varchar(255)
DECLARE @X xml
SET @S = (SELECT Actions + ',' FROM Table1 FOR XML PATH(''))
SELECT @X = CONVERT(xml,'<root><s>' + REPLACE(@S,',','</s><s>') + '</s></root>')
SELECT count(distinct [Value])
FROM (
SELECT [Value] = T.c.value('.','varchar(20)')
FROM @X.nodes('/root/s') T(c)) AS Result
WHERE [Value] > 0
<强> Results 强>:
| COLUMN_0 |
|----------|
| 8 |
编辑:
我认为这正是您所寻找的:
MS SQL Server 2008架构设置:
查询1 :
DECLARE @X xml
SELECT @X = CONVERT(xml,replace('
<root>
<actions>10,12,15</actions>
<actions>11,12,13</actions>
<actions>15</actions>
<actions>14,15,16,17</actions>
</root>
',',','</actions><actions>'))
SELECT count(distinct [Value])
FROM (
SELECT [Value] = T.c.value('.','varchar(20)')
FROM @X.nodes('/root/actions') T(c)) AS Result
<强> Results 强>:
| COLUMN_0 |
|----------|
| 8 |
答案 2 :(得分:0)
有点混乱,但这里是先创建函数然后调用较低的代码。
/* Helper Function */
CREATE FUNCTION dbo.Split (@sep char(1), @s varchar(8000))
RETURNS table
AS
RETURN (
WITH splitter_cte AS (
SELECT CHARINDEX(@sep, @s) as pos, 0 as lastPos
UNION ALL
SELECT CHARINDEX(@sep, @s, pos + 1), pos
FROM splitter_cte
WHERE pos > 0
)
SELECT SUBSTRING(@s, lastPos + 1,
case when pos = 0 then 80000
else pos - lastPos -1 end) as chunk
FROM splitter_cte
)
GO
---------------- End of Function
/* Function Call */
Declare @Actions varchar(1000)
SELECT @Actions = STUFF((SELECT ',' + actions
FROM tblActions
ORDER BY actions
FOR XML PATH('')), 1, 1, '')
SELECT Distinct *
FROM dbo.Split(',', @Actions)
OPTION(MAXRECURSION 0);
答案 3 :(得分:0)
如果您有一个Actions
表,每个可能的操作ID都有一行,您可以使用连接执行此操作:
select count(distinct a.ActionId)
from t join
Actions a
on ','+t.Actions+',' like '%,'+cast(a.ActionId as varchar(255))+',%';
如果你知道动作在某个范围内,你也可以创建一个数字表(使用CTE)。