如何在表格上选择并计算出现的一些值

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) 中,因为这些只是状态表中存在的可接受值。

我们可以假设表 Country 如下所示:

国家:

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 国家表和两个值不正确的样本(错误的国家和站点)

以上是关于如何在表格上选择并计算出现的一些值的主要内容,如果未能解决你的问题,请参考以下文章

如何在一页上选择产品数量并将值传递给 cart.php

如何在 SQL 中的一个字段上选择不重复的记录?

如何做到这一点,当在OptionMenu上选择一个Option并按下一个按钮,然后对该特定选项进行操作时

如何在 c# 2.0/3.0 上选择指定值的 xmlelements xmlnodes xmlattributes

在 UITableView 中的 viewdidload 上选择 Cells,基于 String Array (Swift)

如何根据单元格的所有可能值保存多个电子表格?