簡體   English   中英

SQL計算字段中的不同值

[英]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

SQL小提琴

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 |

編輯:

我認為這正是您所尋找的:

SQL小提琴

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM