8

我向您寻求帮助是因为我不太了解 SQL。

我需要从表列中计算一些值的出现次数,以实现类似于统计表的效果,如下图所示:

需要的结果:

在此处输入图像描述

评论:

我的结果表需要有前两列(contry 和 site)来自第一个表“Violations”,接下来的 5 列将包含 Status 表中每个可能的 id 值中的“Violations”中出现的 status_id 的数量(计数)。

解释:

所以,我有两个表:违规和状态。请看我的sqlfiddle

违规行为:

  • 身份证长,
  • 国家 varchar(20),
  • 网站 varchar(20),
  • status_id long, <--这是状态表中的状态id。
  • ...在这种情况下其他列不重要

地位:

  • 身份证长,
  • status long 列“status”具有映射到字符串值的值 (1-4):Suspected Violation (1)、Confirmed Violation (2)、Confirmed No Violation (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 应该计算例如在 DB Country 表中不存在或名称/id 错误的国家/地区的出现次数,这就是为什么在这里被视为Unknown(我忘了提到 DB 中有表Country)。站点也是如此,Unknown站点意味着有人在 Violations.status_id 中输入了错误的值,而不是在范围 (1-4) 中,因为这些只是状态表中存在的可接受值。

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

国家:

  • 身份证长,
  • 名称 varchar(30)

请帮助我编写包含这 3 个条件的正确 sql 查询,因为我有一个大问题要做。

4

2 回答 2

0

使用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

希望这可以帮助

参考with rollup文档_

小提琴

于 2013-03-12T12:30:26.197 回答
0

All case 可以使用语句轻松完成(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
于 2013-03-12T12:28:38.973 回答