按列值统计的 SQL 计数

huangapple go评论48阅读模式
英文:

SQL count by column values

问题

下面是你要翻译的内容:

I'm trying to count multiple values in multiple coluns in a table and I did that:

TABLE

id risk record api
1 OK OK NO
2 OK OK OK
3 OK OK OK
4 OK NO OK
5 NO OK NO

SQL:

select 'risk' as nm_test, risk as tst_result, count(*) as qty 
  from table
  group by risk 

union 

select 'record' as nm_test, record as tst_result, count(*) as qty
  from table
  group by record

union

select 'api' as nm_test, api as tst_result, count(*) as qty
  from table
  group by api

结果如下表所示:

nm_test tst_result qty
risk OK 4
risk NO 1
record OK 4
record NO 1
api OK 3
api NO 2

但是,相反地,我希望结果表格像这样旋转:

nm_test OK NO
risk 4 1
record 4 1
api 3 2

我尝试过,但是无法弄清楚窍门!任何帮助都将是宝贵的。

干杯。

英文:

I'm trying to count multiple values in multiple coluns in a table and I did that:

TABLE

id risk record api
1 OK OK NO
2 OK OK OK
3 OK OK OK
4 OK NO OK
5 NO OK NO

SQL:

select 'risk' as nm_test, risk as tst_result, count(*) as qty 
  from table
  group by risk 

union 

select 'record' as nm_test, record as tst_result, count(*) as qty
  from table
  group by record

union

select 'api' as nm_test, api as tst_result, count(*) as qty
  from table
  group by api

The result is the following table:

nm_test tst_result qty
risk OK 4
risk NO 1
record OK 4
record NO 1
api OK 3
api NO 2

But, instead, I would like to have the result table pivoted like this:

nm_test OK NO
risk 4 1
record 4 1
api 3 2

I tried to do that, but I was unable to figure out the trick! Any help would be valuable.

Cheers.

答案1

得分: 1

如果您有固定列要进行数据透视,值只有 'OK' 和 'NO',则:

选择 'risk' 作为 nm_test,
        计算(case 当 risk = 'OK' 时 1 end) as 'OK',
        计算(case 当 risk = 'NO' 时 1 end) as 'NO'
从 mytable 中
联合全部
选择 'record',
        计算(case 当 record = 'OK' 时 1 end),
        计算(case 当 record = 'NO' 时 1 end)
从 mytable 中
联合全部
选择 'api',
        计算(case 当 api = 'OK' 时 1 end),
        计算(case 当 api = 'NO' 时 1 end)
从 mytable 中
英文:

If you have a fixed columns to pivot, and values are 'OK' and 'NO' only then :

select 'risk' as nm_test, 
        count(case when risk = 'OK' then 1 end) as 'OK',
        count(case when risk = 'NO' then 1 end) as 'NO'
from mytable
union all
select 'record', 
        count(case when record = 'OK' then 1 end),
        count(case when record = 'NO' then 1 end)
from mytable
union all
select 'api', 
        count(case when api = 'OK' then 1 end),
        count(case when api = 'NO' then 1 end)
from mytable

Demo here

答案2

得分: 0

尝试这个:

SELECT
  nm_test,
  SUM(CASE WHEN tst_result = 'OK' THEN qty ELSE 0 END) AS OK,
  SUM(CASE WHEN tst_result = 'NO' THEN qty ELSE 0 END) AS NO
FROM (
  SELECT 'risk' AS nm_test, risk AS tst_result, COUNT(*) AS qty
  FROM mytable
  GROUP BY risk

  UNION ALL
  SELECT 'record' AS nm_test, record AS tst_result, COUNT(*) AS qty
  FROM mytable
  GROUP BY record

  UNION ALL
  SELECT 'api' AS nm_test, api AS tst_result, COUNT(*) AS qty
  FROM mytable
  GROUP BY api
) subquery
GROUP BY nm_test;
英文:

Try this:

SELECT
  nm_test,
  SUM(CASE WHEN tst_result = 'OK' THEN qty ELSE 0 END) AS OK,
  SUM(CASE WHEN tst_result = 'NO' THEN qty ELSE 0 END) AS NO
FROM (
  SELECT 'risk' AS nm_test, risk AS tst_result, COUNT(*) AS qty
  FROM mytable
  GROUP BY risk

  UNION ALL
  SELECT 'record' AS nm_test, record AS tst_result, COUNT(*) AS qty
  FROM mytable
  GROUP BY record

  UNION ALL
  SELECT 'api' AS nm_test, api AS tst_result, COUNT(*) AS qty
  FROM mytable
  GROUP BY api
) subquery
GROUP BY nm_test;

答案3

得分: 0

忘记使用 UNION

在 PostgreSQL 中,从列到行的数据透视可以通过将数据转换为 jsonb 类型来完成。这在将来需要添加更多测试时会很有帮助。

with pivot as (
  select j.*
    from mytable
   cross join lateral jsonb_each_text(to_jsonb(mytable) - 'id') 
                        as j(nm_test, tst_result)
)
select nm_test, 
       count(*) filter (where tst_result = 'OK') as ok,
       count(*) filter (where tst_result = 'NO') as no
  from pivot
 group by nm_test;

使用 - id 可以从结果中去掉该列。

在聚合函数上使用 filter 可以将数据透视回列。这在可能的结果有限且已知的情况下非常有用。

工作示例

英文:

Forget using UNION.

Pivoting from columns to rows in PostgreSQL can be done by casting into and out of jsonb. This helps if you will be adding more tests in the future.

with pivot as (
  select j.*
    from mytable
   cross join lateral jsonb_each_text(to_jsonb(mytable) - 'id') 
                        as j(nm_test, tst_result)
)
select nm_test, 
       count(*) filter (where tst_result = 'OK') as ok,
       count(*) filter (where tst_result = 'NO') as no
  from pivot
 group by nm_test;

Using - id gets rid of that column from the results.

Using filter on the aggregates pivots back to columns. This is useful so long as the possible results are finite and known.

Working example.

huangapple
  • 本文由 发表于 2023年7月3日 23:07:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/76606000.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定