有没有办法在 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
进行分组,然后查看每个组(A
或B
)在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 = 1
在 true
时返回 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 中对组执行操作?的主要内容,如果未能解决你的问题,请参考以下文章
C#中对SQl数据库进行插入操作,有返回受影响的行数,执行结果是“添加成功”但是在数据困中却没有数据
有没有办法在 Python 中对 FITS 文件使用算术运算?