如何在表格上选择并计算出现的一些值
Posted
技术标签:
【中文标题】如何在表格上选择并计算出现的一些值【英文标题】:How to select on table and count occurrences some values 【发布时间】:2013-02-27 22:49:45 【问题描述】:我向你寻求帮助是因为我不太了解 SQL。
我需要从表列中计算一些值的出现次数,以达到如下图所示的统计表效果:
需要的结果:
评论:
我的结果表需要有前两列(contry 和 site)来自第一个表“Violations”,接下来的 5 列将包含每个可能的 id 值中“Violations”中 status_id 出现次数(计数)状态表。
解释:
所以,我有两个表:Violations 和 Status。请看我的sqlfiddle
违规:
id 长, 国家/地区 varchar(20), 站点 varchar(20), status_id long, ...在这种情况下其他不重要的列状态:
id 长, 状态长 “状态”列的值 (1-4) 映射到字符串值:疑似违规 (1)、确认违规 (2)、确认无违规 (3)、未确定 (4)在我的加入(或仅基于一个表违规)的结果中,表应该包含列:
来自违规表:“国家/地区”和“网站” 来自状态表:“怀疑违规”、“确认违规”、“确认无违规”、“未确定”、“总计”(其中此列是违规表中出现的计数器)。当前状态和新要求:
第一次尝试在下面完成(感谢 bluefeet),几乎完美......
select v.country,
v.site,
SUM(case when s.id = 1 then 1 else 0 end) Total_SuspectedViolations,
SUM(case when s.id = 2 then 1 else 0 end) Total_ConfirmedViolations,
SUM(case when s.id = 3 then 1 else 0 end) Total_ConfirmedNoViolations,
SUM(case when s.id = 4 then 1 else 0 end) Total_NotDetermined,
COUNT(*) Total
from violations v
inner join status s
on v.status_id = s.id
group by v.country, v.site
或不加入:
select v.country,
v.site,
SUM(case when v.status_id = 1 then 1 else 0 end) Total_SuspectedViolations,
SUM(case when v.status_id = 2 then 1 else 0 end) Total_ConfirmedViolations,
SUM(case when v.status_id = 3 then 1 else 0 end) Total_ConfirmedNoViolations,
SUM(case when v.status_id = 4 then 1 else 0 end) Total_NotDetermined,
COUNT(*) Total
from violations v
group by v.country, v.site
...但不包括您在图片中看到的 3 个问题。我的意思是:
“-全部-”应该计算所有国家/地区的出现次数 "- Unknown -" 应该计算某些未识别国家/地区的出现次数 “- 全部 -”(针对每个国家/地区)- 应计算一个国家/地区内的出现次数补充说明:
-Unknown-
含义:
Unknown 应该计算例如在 DB Country 表中不存在或名称/ID 错误的国家/地区的出现次数,这就是为什么这里将其视为 Unknown
(我忘了提到 DB 中有表 Country
) .
站点也是如此,站点的Unknown
意味着有人在 Violations.status_id 中输入了错误的值,而不是在范围 (1-4) 中,因为这些只是状态表中存在的可接受值。
国家:
id 长, 名称 varchar(30)请帮助我编写包含这 3 个条件的正确 sql 查询,因为我有一个大问题要做。
【问题讨论】:
如何指定Unknown
国家/地区?
你能确认你使用的是什么数据库吗?
Unknown
应该计算国家/地区的出现次数,例如在 DB Country 表中不存在或名称/id 错误的国家/地区,这就是为什么在这里被视为未知的原因(我忘了提到有表 Country在数据库中)。站点也是如此,站点的Unknown
意味着有人在 Violations.status_id 中输入了错误的值,而不是在范围 (1-4) 中,因为这些只是状态表中存在的可接受值。
我正在使用 Oracle 11g 数据库
@Roman 你花了多少时间来写和解释问题? :P 感谢您的努力
【参考方案1】:
All 可以使用UNION
语句轻松完成(结果见sqlFiddle):
(SELECT v.country,
v.site,
SUM(CASE WHEN v.status_id = 1 THEN 1 ELSE 0 END) Total_SuspectedViolations,
SUM(CASE WHEN v.status_id = 2 THEN 1 ELSE 0 END) Total_ConfirmedViolations,
SUM(CASE WHEN v.status_id = 3 THEN 1 ELSE 0 END) Total_ConfirmedNoViolations,
SUM(CASE WHEN v.status_id = 4 THEN 1 ELSE 0 END) Total_NotDetermined,
COUNT(*) Total,
0 'isAll'
FROM violations v
GROUP BY v.country, v.site)
union(
SELECT v.country,
'- All -',
SUM(CASE WHEN v.status_id = 1 THEN 1 ELSE 0 END) Total_SuspectedViolations,
SUM(CASE WHEN v.status_id = 2 THEN 1 ELSE 0 END) Total_ConfirmedViolations,
SUM(CASE WHEN v.status_id = 3 THEN 1 ELSE 0 END) Total_ConfirmedNoViolations,
SUM(CASE WHEN v.status_id = 4 THEN 1 ELSE 0 END) Total_NotDetermined,
COUNT(*) Total,
1 'isAll'
FROM violations v
GROUP BY v.country)
UNION (
SELECT '- All -',
'- All -',
SUM(CASE WHEN v.status_id = 1 THEN 1 ELSE 0 END) Total_SuspectedViolations,
SUM(CASE WHEN v.status_id = 2 THEN 1 ELSE 0 END) Total_ConfirmedViolations,
SUM(CASE WHEN v.status_id = 3 THEN 1 ELSE 0 END) Total_ConfirmedNoViolations,
SUM(CASE WHEN v.status_id = 4 THEN 1 ELSE 0 END) Total_NotDetermined,
COUNT(*) Total,
1 'isAll'
FROM violations v)
ORDER BY country, isAll DESC, site
但是,这种查询的性能可能不是很好,所以我并不是说它是最好的解决方案 - 但它确实有效。
带有“未知”的版本
http://www.sqlfiddle.com/#!2/abfb7/21
(SELECT IF(c.name IS NULL, '- Unknow -', c.name) as name,
v.site,
SUM(CASE WHEN v.status_id = 1 THEN 1 ELSE 0 END) Total_SuspectedViolations,
SUM(CASE WHEN v.status_id = 2 THEN 1 ELSE 0 END) Total_ConfirmedViolations,
SUM(CASE WHEN v.status_id = 3 THEN 1 ELSE 0 END) Total_ConfirmedNoViolations,
SUM(CASE WHEN v.status_id = 4 THEN 1 ELSE 0 END) Total_NotDetermined,
COUNT(*) Total,
0 'isAll'
FROM violations v LEFT JOIN country c ON c.name = v.country
GROUP BY c.name, v.site)
union(
SELECT IF(c.name IS NULL, '- Unknow -', c.name) as name,
'- All -',
SUM(CASE WHEN v.status_id = 1 THEN 1 ELSE 0 END) Total_SuspectedViolations,
SUM(CASE WHEN v.status_id = 2 THEN 1 ELSE 0 END) Total_ConfirmedViolations,
SUM(CASE WHEN v.status_id = 3 THEN 1 ELSE 0 END) Total_ConfirmedNoViolations,
SUM(CASE WHEN v.status_id = 4 THEN 1 ELSE 0 END) Total_NotDetermined,
COUNT(*) Total,
1 'isAll'
FROM violations v LEFT JOIN country c ON c.name = v.country
GROUP BY c.name)
UNION (
SELECT '- All -',
'- All -',
SUM(CASE WHEN v.status_id = 1 THEN 1 ELSE 0 END) Total_SuspectedViolations,
SUM(CASE WHEN v.status_id = 2 THEN 1 ELSE 0 END) Total_ConfirmedViolations,
SUM(CASE WHEN v.status_id = 3 THEN 1 ELSE 0 END) Total_ConfirmedNoViolations,
SUM(CASE WHEN v.status_id = 4 THEN 1 ELSE 0 END) Total_NotDetermined,
COUNT(*) Total,
1 'isAll'
FROM violations v LEFT JOIN country c ON c.name = v.country)
ORDER BY name, isAll DESC, site
【讨论】:
@MarcinJaraszek 您的解决方案已根据我的要求进行了调整,但如何为国家和网站添加Unknown
?
你能扩展你的国家表和它与现有表之间的连接吗?
是的,扩展了 sql fiddle。不幸的是,在我的源数据库中,Violations 中的国家列也是字符串值。
第二个问题是这个 sql 在 Oracle 中是不可接受的;/ 出现错误:0 'isAll'
语句。即使完全删除它也不会编译:LOG:“查询块的结果列数不正确”
你很棒,Marcin,效果很好!很抱歉给您带来不便,但我之前对 sql fiddle 并不熟悉。您是否怀疑为什么它没有在 Oracle 中编译?这里:sqlfiddle.com/#!4/93c94/1【参考方案2】:
使用with rollup
,您将获得所需的总和字段
select v.country,
v.site,
SUM(case when s.id = 1 then 1 else 0 end) Total_SuspectedViolations,
SUM(case when s.id = 2 then 1 else 0 end) Total_ConfirmedViolations,
SUM(case when s.id = 3 then 1 else 0 end) Total_ConfirmedNoViolations,
SUM(case when s.id = 4 then 1 else 0 end) Total_NotDetermined,
COUNT(*) Total
from violations v
inner join status s
on v.status_id = s.id
group by v.country, v.site WITH ROLLUP
希望对你有帮助
REFER 用于with rollup
文档
FIDDLE
【讨论】:
很好,但是如何为国家和网站添加Unknown
?
请提供一些我无法获取的未知类型的示例记录
sqlfiddle.com/#!2/abfb7/1/0 这里是更新的 sqlfiddle 国家表和两个值不正确的样本(错误的国家和站点)以上是关于如何在表格上选择并计算出现的一些值的主要内容,如果未能解决你的问题,请参考以下文章
如何做到这一点,当在OptionMenu上选择一个Option并按下一个按钮,然后对该特定选项进行操作时
如何在 c# 2.0/3.0 上选择指定值的 xmlelements xmlnodes xmlattributes
在 UITableView 中的 viewdidload 上选择 Cells,基于 String Array (Swift)