【问题标题】:Is there a way to perform operations on groups in SQL?有没有办法在 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

标签: sql sqlite aggregate-functions


【解决方案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                        |
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-10-10
          • 2013-01-29
          • 2013-05-12
          • 1970-01-01
          • 2014-07-16
          • 1970-01-01
          相关资源
          最近更新 更多