【问题标题】:SQL query to select multiple valuesSQL查询选择多个值
【发布时间】:2014-02-05 14:39:04
【问题描述】:

我正在为我的公司创建流量报告,但我真的被这段代码卡住了..

我有一个报告编号,以及用编号表示的事故类型,即; 1-轻微,2-严重,3-致命,4-未受伤。

通常事故报告包含多个数字,例如:

报告编号 2014123 有一名驾驶员严重受伤“2”,乘客未受伤“4”。

所以当我触发选择查询 where report number=2014123 时,我得到两条记录,一条为“2”伤害,另一条为“4”。

在上述情况下,事故被视为“严重”,因为它包含“2”。 '4' 不考虑,因为乘客没有受伤。带有(轻微、严重、致命)的伤害代码的处理程度高于(未受伤)。

如何生成严重伤害报告(即代码“2”)并将伤害计为“2”(因为有两条记录)?

我尝试过的方法:

我尝试使用 SQL Case 语句:

(Case WHEN InjuryCode IN ('1','2','4') THEN 'Serious'
WHEN InjuryCode IN ('1','2','3','4') THEN 'FATAL'
WHEN InjuryCode IN ('1','4') THEN 'SLIGHT'

ELSE 'UNKNOWN'
END) AS ACCIDENT_STATUS

但我得到的只是重复和不正确的数据。

按以下方式优先考虑伤害代码: 3>2>1>4

例如:事故包含伤害代码为:

1,4- slight
2,4- serious
3,4- fatal

1,2,3,4-致命(因为3是最高伤害代码)等等等等..

我希望这不会让您感到困惑,但请多多包涵,我一开始完全糊涂了,但现在我实际上得到了图片,虽然没有解决方案,请帮助!

编辑(来自评论的完整查询):

SELECT REPORTNUMBER, INJURYCODE,
       (CASE WHEN InjuryCode IN ('1','2','4') THEN 'Serious'
             WHEN INJURYCODE IN ('1','2','3','4') THEN 'FATAL'
             WHEN INJURYCODE IN ('1','4') THEN 'SLIGHT' ELSE 'UNKNOWN'
       END) AS ACCIDENT_STATUS
FROM ACCIDENTS
WHERE REPORTNUMBER=20140302

【问题讨论】:

  • 请显示您正在访问的数据的结构和/或带有case语句的完整查询。
  • @GordonLinoff:当然,选择 REPORTNUMBER、INJURYCODE、CASE(当 InjuryCode IN ('1','2','4') THEN 'Serious' WHEN INJURYCODE IN ('1','2 ','3','4') THEN 'FATAL' WHEN INJURYCODE IN ('1','4') THEN '轻微' ELSE 'UNKNOWN' END) 作为 ACCIDENT_STATUS 来自 REPORTNUMBER=20140302 的事故
  • 建议:您不应该将数字放在引号中。它要么是一个不使用引号的数字,要么是一个字符串,所以你应该避免使用无意义的数字。

标签: sql db2 case


【解决方案1】:

injuryCode 的使用表明您需要一个Injury 表(如果您还没有)。理想情况下,这包括您可以订购的某种严重性列 - 如下所示:

CREATE TABLE Injury (injuryCode CHAR(1),
                     severity INTEGER,
                     description VARCHAR(20));

INSERT INTO Injury VALUES ('1', 1, 'Slight'),
                          ('2', 2, 'Serious'),
                          ('3', 3, 'Fatal'),
                          ('4', 0, 'Not Injured');

严格来说,您之前尝试的是根据受伤的明显 id 进行排序 - ids 唯一应该用于连接,否则应被视为随机/未定义值(即,实际值为不重要——重要的是是否有任何东西与之相关)。这些恰好是数字代码(显然存储为字符数据 - 这是完全可以接受的)这一事实无关紧要。

不管怎样,定义了排序表后,我们现在可以安全地查询数据了:

SELECT AggregateAccident.reportNumber, Injury.injuryCode, Injury.description, 
       AggregateAccident.victimCount
FROM (SELECT Accidents.reportNumber, MAX(Injury.severity) as severity, 
             COUNT(*) as victimCount
      FROM Accidents
      JOIN Injury
        ON Injury.injuryCode = Accidents.injuryCode
      GROUP BY Accidents.reportNumber) AggregateAccident
JOIN Injury
  ON Injury.severity = AggregateAccident.severity
ORDER BY AggregateAccident.reportNumber

(还有SQL Fiddle example。感谢 Turophile 的骨架。使用 SQL Server,但这应该适用于任何 RDBMS)。


编辑:

如果不能创建永久表,可以创建临时表:

WITH Injury AS (SELECT a AS injuryCode, b AS severity, c AS description
                FROM (VALUES ('1', 1, 'Slight'),
                             ('2', 2, 'Serious'),
                             ('3', 3, 'Fatal'),
                             ('4', 0, 'Not Injured')) I(a, b, c))
SELECT AggregateAccident.reportNumber, Injury.injuryCode, Injury.description, 
       AggregateAccident.victimCount
FROM (SELECT Accidents.reportNumber, MAX(Injury.severity) as severity, 
             COUNT(*) as victimCount
      FROM Accidents
      JOIN Injury
        ON Injury.injuryCode = Accidents.injuryCode
      GROUP BY Accidents.reportNumber) AggregateAccident
JOIN Injury
  ON Injury.severity = AggregateAccident.severity
ORDER BY AggregateAccident.reportNumber

(和updated SQL Fiddle
WITH 子句构造所谓的公用表表达式 (CTE),基本上是内联视图或临时表定义。这也可以通过子查询来完成,但是当我引用 Injury 两次时,使用 CTE 意味着我只需编写一次包含的信息(如果 CTE 是其他查询的结果,这可能有助于提高性能,也)。最新/当前的 RDBMS 支持此功能(特别是 MySQL 不支持),包括 DB2。

【讨论】:

  • 感谢您的信息!!是的,像这样添加严重性列是非常有意义的,但是,我无权创建或更改表,因为它由客户端 DBA 控制。因此,我正在尝试是否有任何方法而不创建桌子。
  • 是的,这个真的帮助了我!!!我必须从我的办公室下载输出并将其加载到我的本地临时服务器中,之后我才能相应地生成报告。感谢您的帮助,非常感谢您的时间!!
【解决方案2】:

这样的? (未测试)。

SELECT REPORTNUMBER,
       CASE INJURYCODE 
           WHEN 1 THEN 'SLIGHT' 
           WHEN 2 THEN 'Serious'
           WHEN 3 THEN 'FATAL'
           ELSE 'UNKNOWN'
       END ACCIDENT_STATUS,
       INJURYCOUNT
FROM (
   SELECT REPORTNUMBER, 
          MAX(CASE INJURYCODE WHEN 4 THEN 0 ELSE INJURYCODE END) INJURYCODE, 
          COUNT(1) INJURYCOUNT,
   FROM ACCIDENTS
   GROUP BY REPORTNUMBER
)

【讨论】:

  • > 你好,我在没有报告计数的情况下尝试了上面的代码(没有运行)。 >使用您的代码,我得到了这个输出:code 987654322 code 987654322 code 987654322 code 987654322 code 987654322 code 987654322 code 981岁20132略微20133略微20135年致命20136年度20136略有20137致命20138略有201310岁201310岁201310岁20131,20136,201310有2条记录带有“严重”和“轻微”。由于严重高于轻微,我希望报告将事故视为“严重”而不是轻微。那么有什么办法可以覆盖吗?致命事故>严重事故>轻微事故>未受伤 感谢您的宝贵时间
  • 没有看到您的实际表定义和数据(以 CREATE TABLE 和 INSERT 语句的形式),没有人能真正帮助您。祝你好运。
  • 抱歉 mustaccio,我没有准确的表定义。因为它是从客户端创建的,所以我只能访问数据库。虽然通过使用表,我确实知道表字段的数据类型以及表定义的样子:code CREATE TABLE ACCIDENTS(A_DATE DATETIME, REPORTNUMBER VARCHAR(50), INJURYCODE CHAR(1), A_INJURY_ENGLISH VARCHAR(50)); code.Thanks你的时间。
【解决方案3】:

这不是一个答案,而是一种提高你技能的尝试。

如果您将伤害代码存储为这样的数字:

0 = 未受伤 1 = 轻微 2 = 严重 3 = 致命

那么你就可以使用这个清晰简单的SQL了:

select reportnumber, max(injurycode) as injurycode, count(*) as involved
from accidents
group by reportnumber

这里有一个小提琴来说明它:http://sqlfiddle.com/#!2/87faf/1

【讨论】:

  • ... 然后有人决定添加5 = Moderate(应该在SlightSerious 之间)。本质上,您依靠伤害级别的 id 来告诉您其严重程度;这就像期望 Employee 表具有基于员工 ID 排序的层次结构......
  • @turophile:感谢 Turophile 的建议!但是我没有更改数据库及其伤害代码的权限,我目前被分配开发软件,该软件只能用于检索数据。但是,这个建议很完美,如果我是 DBA,我会按照你的步骤进行操作的。
  • @Clockwork-Muse,你是对的,但任何真正的系统都会有另一个表来将代码转换为描述 - 就像你试图处理你的答案一样,可能有一个排名列来给他们输出中的正确顺序。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-01
  • 1970-01-01
  • 2021-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多