6

我正在为我的工作做一项任务,不幸的是,这些表格的设计很糟糕,我不能做太多修改结构(我们这里的主要程序之一多年来一直基于这些过时的表格)。话虽如此,我需要找到一种方法来使用 SQL Server (TSQL) 来计算给定行中不同列的数量。

例子:

我有一个包含列name, fieldA, fieldB, fieldC,fieldD等的表 我想返回一个包含每一行的表,返回name和不同列的数量fieldA-fieldD

视觉上:

  • 吉姆 - 1 - 3 - 4 - 6
  • 约翰 - 1 - 1 - 1 - 2
  • 简 2 - 2 - 3 - 3

会回来

  • 吉姆 - 4
  • 约翰 - 2
  • 简 - 2
4

5 回答 5

10

一种方法是取消透视数据,然后再次对其进行分组。这使您能够使用count(distinct)

select name, count(distinct val)
from t
unpivot (val for col in (FieldA, FieldB, FieldC, FieldD)) unpvt
group by name;

但是,最有效的方法是将所有处理保持在单行上——没有joins 或group bys 或unions。假设没有任何值是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 。最后一个条件确保重复计算不超过一次。

于 2013-07-31T17:47:16.927 回答
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; 
于 2013-07-31T17:49:09.760 回答
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

SQLFIDDLE 演示

于 2013-07-31T17:49:27.813 回答
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 ...

于 2013-07-31T18:04:38.627 回答
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
于 2013-07-31T17:44:50.153 回答