有没有办法在 SQL 中对组执行操作?

Posted

技术标签:

【中文标题】有没有办法在 SQL 中对组执行操作?【英文标题】:Is there a way to perform operations on groups in SQL? 【发布时间】:2019-09-07 06:52:52 【问题描述】:

所以我对 SQL 很陌生,可能没有准确地描述我想要做什么。我有一个包含三列的表,我想按一列分组,看看每组中有多少百分比在另一列中有一定的值。例如表中:

id   col1  col2
----------------
0       A     1
1       A     2
2       B     2
3       B     2
4       A     1

我想按col1 进行分组,然后查看每个组(AB)在col2 中的值为 1 的百分比。我想要的结果是:

col1  percentage_col2_equals_1
------------------------------
   A                      66.7
   B                       0.0

到目前为止我有:

SELECT col1,
((SELECT COUNT(*) FROM my_table
WHERE col2 = 1
GROUP BY col1) / 
(SELECT COUNT(*) FROM my_table
GROUP BY col1) * 100)
FROM my_table
GROUP BY col1;

但这不起作用。任何帮助将不胜感激!

【问题讨论】:

我在 Python 上使用 SQLite3 【参考方案1】:

使用case when

SELECT col1,(coalesce(count(case when col2=1 then col2 end),0)*100.00)/count(*)
from tablename
group by col1

【讨论】:

【参考方案2】:

和每个人的答案一样,只是因为 Postgres 的表现力而把它放在这里:)

现场测试:https://www.db-fiddle.com/f/goL488VaPuZYii7Wik3pFk/4

select
    col1,
    count(*) filter(where col2 = 1) ::numeric / count(*)

from tbl    
group by col1;

输出:

| col1 | ?column?               |
| ---- | ---------------------- |
| A    | 0.66666666666666666667 |
| B    | 0.00000000000000000000 |

若要以百分比表示,小数点后 1 位,请将其乘以 100 并四舍五入为 1:

现场测试:https://www.db-fiddle.com/f/goL488VaPuZYii7Wik3pFk/5

select
    col1,    
    round( 
      count(*) filter(where col2 = 1) ::numeric / count(*) * 100, 
      1 
    ) as p_a      
from tbl    
group by col1;


select
    col1,    
    (
        count(*) filter(where col2 = 1) ::numeric / count(*) * 100
    )::numeric(100,1) as p_b       
from tbl    
group by col1;

输出:

| col1 | p_a  |
| ---- | ---- |
| A    | 66.7 |
| B    | 0.0  |


| col1 | p_b  |
| ---- | ---- |
| A    | 66.7 |
| B    | 0.0  |

【讨论】:

filter (...) 语法实际上是 SQL 标准的一部分,它不是 Postgres 特定的。然而,真正实现这一点的 DBMS 很少(据我所知,其他只有 HSQLDB 和 SQLite) @a_horse_with_no_name 很高兴知道它是 SQL 标准。 Postgres 是最符合 SQL 标准的数据库,当 SQL 标准中有新功能时,它总是处于领先地位,这有时让我觉得某个功能是 Postgres 特有的:D【参考方案3】:

以下查询将返回您的预期结果:

SELECT col1, 
       CAST(((SUM(IIF(col2 = 1, 1, 0))) * 100.0) / COUNT(*) AS DECIMAL(5, 1)) AS percentage_col2_equals_1
FROM my_table
GROUP BY col1;

使用示例数据执行示例:

DECLARE @my_table TABLE (id INT,  col1 CHAR(1),  col2 INT);

INSERT INTO @my_table (id, col1, col2) VALUES
(0, 'A', 1),
(1, 'A', 2),
(2, 'B', 2),
(3, 'B', 2),
(4, 'A', 1);

SELECT col1, CAST(((SUM(IIF(col2 = 1, 1, 0))) * 100.0) / COUNT(*) AS DECIMAL(5, 1)) AS percentage_col2_equals_1
FROM @my_table
GROUP BY col1;

输出:

col1    percentage_col2_equals_1
---------------------------------
A       66.7
B       0.0

【讨论】:

【参考方案4】:
     CREATE TABLE #TEMP
    (ID   INT, 
     COL1 VARCHAR(10), 
     COL2 INT
    );
    INSERT INTO #TEMP
           SELECT 0, 'A',1
           UNION
           SELECT 1, 'A',2
           UNION
           SELECT 2, 'B',2
           UNION
           SELECT 3, 'B',2
           UNION
           SELECT 4, 'A',1;
    SELECT T.COL1, 
           ROUND((CAST(COUNT(CASE
                                 WHEN T.COL2 = 1
                                 THEN T.COL2
                                 ELSE NULL
                             END) AS DECIMAL) / (S.COL2)) * 100.0, 2) AS Percentage_1
    FROM #TEMP T
         JOIN
    (
        SELECT COUNT(COL2) COL2, 
               COL1
        FROM #TEMP
        GROUP BY COL1
    ) S ON S.COL1 = T.COL1
    GROUP BY T.COL1, 
             S.COL2;

【讨论】:

您可以使用小提琴来避免在您的答案中重复数据。这是一个很好的:db-fiddle.com 无需手动键入 DDL 和创建数据,只需单击 Text to DDL,然后粘贴 OP 的文本数据。它将为您生成 DDL 并创建数据 谢谢,我会试试的。【参考方案5】:

这将起作用:

CREATE TABLE Table1
    ("id" int, "col1" varchar2(1), "col2" int)
;
//do inserts
select aa."col1",((select count(*) from Table1 b 
where b."col1"=aa."col1" and b."col2"=1 )*100/(select count(*) 
from Table1 c where c."col1"='A' )) percentge
from Table1 aa
group by aa."col1"
; 

输出:

A   66.66666666666666666666666666666666666667
B   0

【讨论】:

【参考方案6】:

在 SQLite 中,表达式 col2 = 1true 时返回 1,在 false 时返回 0。 所以你只需要col2 = 1 的平均值,然后将其四舍五入到小数点后一位:

select
  col1,
  round(100.0 * avg(col2 = 1), 1) percentage_col2_equals_1
from tablename  
group by col1

请参阅demo。 结果:

| col1 | percentage_col2_equals_1 |
| ---- | ------------------------ |
| A    | 66.7                     |
| B    | 0                        |

【讨论】:

以上是关于有没有办法在 SQL 中对组执行操作?的主要内容,如果未能解决你的问题,请参考以下文章

如何在php中对组中的值求和?

C#中对SQl数据库进行插入操作,有返回受影响的行数,执行结果是“添加成功”但是在数据困中却没有数据

有没有办法在 Python 中对 FITS 文件使用算术运算?

plsql 中执行UPDATE误操作 怎样回滚。执行update后,并没有点提交,但是我把SQL窗口关掉了,有啥办法?

在Django中对多个表进行筛选和排序

有没有办法在 graphQL 中对查询进行分组?