【问题标题】: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 感谢您的努力

标签: sql jpa join count oracle11g


【解决方案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 国家表和两个值不正确的样本(错误的国家和站点)
猜你喜欢
  • 2013-02-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-15
  • 1970-01-01
  • 2017-01-04
  • 1970-01-01
相关资源
最近更新 更多