[英]SQL Count distinct values within the field
我有這個奇怪的場景(至少對我而言)我有一個表(實際上是一個結果集,但我想讓它變得更簡單),如下所示:
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函數,只是讓一切變得更容易。
讓我知道是否還有其他我應該說的話。
使用類似於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)
這是演示: http : //sqlfiddle.com/#!3/5e706/3/0
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
結果 :
| 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
結果 :
| COLUMN_0 |
|----------|
| 8 |
有點亂,但這里是先創建函數,然后調用較低的代碼。
/* 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);
如果您有一個Actions
表,每個可能的操作ID都有一行,您可以使用連接執行此操作:
select count(distinct a.ActionId)
from t join
Actions a
on ','+t.Actions+',' like '%,'+cast(a.ActionId as varchar(255))+',%';
如果您知道操作在某個范圍內,您還可以創建一個數字表(使用CTE)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.