我们如何计算具有唯一列的 table 的多个列的特定值

how do we have count of a specific values for multiple columns with table having a unique column

如果我有 table 喜欢 :

u_id    A   B   C   D
----------------------------------
jud     1   1   0   1
bud     0   0   1   0
cud     1   1   0   1
nud     0   0   1   0
dud     1   0   0   1
aud     0   1   1   0
fud     1   0   1   1

哪个 sql 可用于获得如下输出:

    count  0    count 1
-----------------------
A          3    4
B          4    3
C          3    4
D          3    4

行或列无关紧要,只需要计算 table 中多个列的特定值计数即可。

它可以是特定的字符串值以及 'yes' 或 'no'

而不是 0 和 1

谢谢

使用UNION ALL和聚合。假设列中唯一可能的值是 01:

SELECT 'A' col, COUNT(*) - SUM(A) count0, SUM(A) count1 FROM mytable
UNION ALL SELECT 'B', COUNT(*) - SUM(B), SUM(B) FROM mytable
UNION ALL SELECT 'C', COUNT(*) - SUM(C), SUM(C) FROM mytable
UNION ALL SELECT 'D', COUNT(*) - SUM(D), SUM(D) FROM mytable

Demo on DB Fiddle:

| col | count0 | count1 |
| --- | ------ | ------ |
| A   | 3      | 4      |
| B   | 4      | 3      |
| C   | 3      | 4      |
| D   | 3      | 4      |

如果除 0/1 之外的其他值都是可能的,那么您可以将 SELECT 更改为,例如 'yes'/'no',然后:

SELECT 
    'A' col, 
    SUM(CASE WHEN A = 'no'  THEN 1 ELSE 0 END) count_no,
    SUM(CASE WHEN A = 'yes' THEN 1 ELSE O END) count_yes
FROM mytable
GROUP BY col
UNION ALL SELECT 
    'B' col, 
    SUM(CASE WHEN B = 'no'  THEN 1 ELSE 0 END),
    SUM(CASE WHEN B = 'yes' THEN 1 ELSE 0 END)
FROM mytable
GROUP BY col
UNION ALL SELECT 
    'C' col, 
    SUM(CASE WHEN C = 'no'  THEN 1 ELSE 0 END),
    SUM(CASE WHEN C = 'yes' THEN 1 ELSE 0 END)
FROM mytable
GROUP BY col
UNION ALL SELECT 
    'D' col, 
    SUM(CASE WHEN D = 'no'  THEN 1 ELSE 0 END),
    SUM(CASE WHEN D = 'yes' THEN 1 ELSE 0 END)
FROM mytable
GROUP BY col

如果你对单行没问题,你可以这样做:

select sum(a), sum(1-a), sum(b), sum(1-b), sum(c), sum(1-c), sum(d), sum(1-d)
from t;

这种方法的优点是t只读一次。如果它是一个复杂的视图,则更是如此。

考虑到这一点,您可以取消透视此结果:

select v.x,
       (case when v.x = 'a' then a_0 end) as a_0,
       (case when v.x = 'a' then a_1 end) as a_1,
       (case when v.x = 'b' then b_0 end) as b_0,
       (case when v.x = 'b' then b_1 end) as b_1,
       (case when v.x = 'c' then c_0 end) as c_0,
       (case when v.x = 'c' then c_1 end) as c_1,
       (case when v.x = 'd' then d_0 end) as d_0,
       (case when v.x = 'd' then d_1 end) as d_1
from (select sum(a) as a_1, sum(1-a) as a_0, 
             sum(b) as b_1, sum(1-b) as b_0, 
             sum(c) as c_1, sum(1-c) as c_0, 
             sum(d) as d_1, sum(1-d) as d_0 
      from t
     ) s cross join
     (values ('a'), ('b'), ('c'), ('d')) v(x)  -- may require a subquery

您没有提到您正在使用的数据库,但在 Oracle 中,您可以同时使用 DECODECOUNT 以使其相当干净:

SELECT 'A' AS FIELD_NAME,
            COUNT(DECODE(A, 0, 0, NULL)) AS ZERO_COUNT,
            COUNT(DECODE(A, 0, NULL, A)) AS NON_ZERO_COUNT
  FROM TEST_TABLE UNION ALL
SELECT 'B', COUNT(DECODE(B, 0, 0, NULL)),
            COUNT(DECODE(B, 0, NULL, A))
  FROM TEST_TABLE UNION ALL
SELECT 'C', COUNT(DECODE(C, 0, 0, NULL)),
            COUNT(DECODE(C, 0, NULL, A))
  FROM TEST_TABLE UNION ALL
SELECT 'D', COUNT(DECODE(D, 0, 0, NULL)),
            COUNT(DECODE(D, 0, NULL, A))
  FROM TEST_TABLE

dbfiddle here