我正在为我的工作完成一项任务,不幸的是,这些表的设计非常糟糕,而且我不能做太多修改结构(我们这里的一个主要程序已基于这些过时的表多年)。话虽这么说,我需要找到一种方法来使用SQL Server(TSQL)来计算给定行中不同列的数量。
我有一个包含name
,fieldA
,fieldB
,fieldC
,fieldD
等列的表格
我想返回一个包含每一行的表格,返回name
以及fieldA
的不同列数 - fieldD
会返回
答案 0 :(得分:10)
实现此目的的一种方法是通过取消数据,然后再将其分组。这使您可以使用count(distinct)
:
select name, count(distinct val)
from t
unpivot (val for col in (FieldA, FieldB, FieldC, FieldD)) unpvt
group by name;
但是,最有效的方法是将所有处理保留在一行 - 没有join
或group by
或union
。假设没有值为NULL
,则以下内容适用于4列:
select name,
4 - ((case when FieldA in (FieldB, FieldC, FieldD) then 1 else 0 end) +
(case when FieldB in (FieldC, FieldD) then 1 else 0 end) +
(case when FieldC in (FieldD) then 1 else 0 end)
)
from t;
即,从列总数开始。每当一列与以后的列相似时,减去1。最后一个条件确保重复项不会被计算多次。
答案 1 :(得分:6)
DECLARE @x TABLE
(
Name VARCHAR(32),
A VARCHAR(32),
B VARCHAR(32),
C VARCHAR(32),
D VARCHAR(32)
);
INSERT @x VALUES
('Jim', 1,3,4,6),
('John',1,1,1,2),
('Jane',2,2,3,3);
SELECT Name, NumCols = COUNT(DISTINCT x)
FROM @x AS x
UNPIVOT (x FOR y IN (A,B,C,D)) AS up
GROUP BY Name
ORDER BY NumCols DESC;
答案 2 :(得分:4)
您可以使用UNPIVOT
运算符将列转换为行,然后计算不同的值:
select c_name
, count(distinct val) as distinct_vals
, count(val) as total_vals
from ( select c_name
, val
from t1
unpivot(
val for col in(col1, col2, col3, col4)
) unpvt
) s
group by c_name
结果:
C_NAME DISTINCT_VALS TOTAL_VALS
Jane 2 4
Jim 4 4
John 2 4
答案 3 :(得分:4)
又一种方法:
SELECT
Name,
Cnt = (SELECT COUNT(DISTINCT V) FROM (VALUES (A), (B), (C), (D)) AS v (V))
FROM atable
;
使用SQL Server 2008语法(VALUES
行构造函数)。它可以通过将VALUES (A), (B), ...
替换为SELECT A UNION ALL SELECT B UNION ALL ...
来适应早期版本。
答案 4 :(得分:0)
Select Name,Count(*) From
(select Name,FieldA from test10
Union
select Name,FieldB from test10
union
select Name,FieldC from test10
Union
select Name,FieldD from test10)as a
Group by name