如何计算 N 列中唯一值的数量

时间:2021-06-04 19:53:03

标签: sql sql-server tsql

如何验证列中唯一值的数量?例如我有一张桌子:

<头>
Shop_1 Shop_2 Shop_3 Shop_4
阿迪达斯 耐克 阿迪达斯
锐步 耐克 阿迪达斯 亚瑟士
Ascics 亚瑟士 亚瑟士 亚瑟士
耐克 耐克 耐克 阿迪达斯

对于这个表,我想有一个额外的列,其中包含有关在给定记录中出现的唯一商店数量的信息。结果应如下所示:

  1. 第一行:2(因为有耐克和阿迪达斯)
  2. 第二行:4
  3. 第三排:1(有 4 家商店,但都是 Asics)
  4. 第四行:2
CREATE TABLE shops
(ID INTEGER PRIMARY KEY,
shop1 CHAR(20),
shop2 CHAR(20),
shop3 CHAR(20),
shop4 CHAR(20),
expected_result INT )

INSERT INTO shops VALUES (1, 'Adidas', 'Nike', 'Adidas', null, 2);
INSERT INTO shops VALUES (2, 'Reebok', 'Nike', 'Adidas', 'Asics', 4);
INSERT INTO shops VALUES (3, 'Asics', 'Asics', 'Asics', 'Asics', 1);
INSERT INTO shops VALUES (4, 'Nike', 'Nike', 'Nike', 'Adidas', 2);

4 个答案:

答案 0 :(得分:3)

请尝试以下方法。

SQL #1

-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, Shop_1 VARCHAR(20), Shop_2 VARCHAR(20), Shop_3 VARCHAR(20), Shop_4 VARCHAR(20));
INSERT INTO @tbl (Shop_1, Shop_2, Shop_3, Shop_4) VALUES
('Adidas', 'Nike', 'Adidas', NULL),
('Reebok', 'Nike', 'Adidas', 'Asics'),
('Asics', 'Asics', 'Asics', 'Asics'),
('Nike', 'Nike', 'Nike', 'Adidas');
-- DDL and sample data population, end

SELECT * 
    , (
       SELECT Shop_1, Shop_2, Shop_3, Shop_4
       FOR XML PATH(''), TYPE, ROOT('root')
    )
    .value('count(distinct-values(/root/*/text()))','INT') AS [Counter]
FROM @tbl AS p;

SQL #2

它允许处理列列表变化的场景: Shop_1、Shop_2、...、ShopN。

SELECT * 
    , (
       SELECT *
       FROM @tbl AS c 
       WHERE c.ID = p.ID
       FOR XML PATH(''), TYPE, ROOT('root')
    )
    .value('count(distinct-values(/root/*[local-name()!="ID"]/text()))','INT') AS [UniqueCounter]
FROM @tbl AS p;

输出

+----+--------+--------+--------+--------+---------+
| ID | Shop_1 | Shop_2 | Shop_3 | Shop_4 | Counter |
+----+--------+--------+--------+--------+---------+
|  1 | Adidas | Nike   | Adidas | NULL   |       2 |
|  2 | Reebok | Nike   | Adidas | Asics  |       4 |
|  3 | Asics  | Asics  | Asics  | Asics  |       1 |
|  4 | Nike   | Nike   | Nike   | Adidas |       2 |
+----+--------+--------+--------+--------+---------+

答案 1 :(得分:2)

您可以这样做的一种方法是使用 cross apply 旋转,然后使用 count

select * 
from #t
cross apply (
    select Count (distinct shops) UniqueCount
    from (
        values (shop_1),(shop_2),(shop_3),(shop_4)
    )x(shops)
)a

DB Fiddle

答案 2 :(得分:1)

动态解决方案可能是使用目录表(information_schema.columns),例如

DECLARE @cols1 AS NVARCHAR(MAX), @cols2 AS NVARCHAR(MAX),  @query AS NVARCHAR(MAX)

SET @cols1 = ( SELECT STRING_AGG(QUOTENAME([column_name]),',')
                 FROM information_schema.columns
                WHERE [column_name] != 'ID'
                  AND [table_name]='shops');
               
SET @cols2 = ( SELECT STRING_AGG('COUNT('+QUOTENAME([column_name])+') 
                                   OVER (PARTITION BY ID ORDER BY ID)','+') AS total 
                 FROM information_schema.columns
                WHERE [column_name] != 'ID');
               
SET @query = N'SELECT [ID], '+ @cols1 +',' + @cols2 +  
             N'  FROM [shops]';
--SELECT @query;
EXEC sp_executesql @query;

Demo

答案 3 :(得分:-1)

只需计算列的不同值即可。

SELECT
    COUNT(DISTINCT shop_1) count1, 
    COUNT(DISTINCT shop_2) count2, 
    COUNT(DISTINCT shop_3) count3, 
    COUNT(DISTINCT shop_4) count4
FROM
    your_table
相关问题