SQL查询:将类似记录合并到多个列中

时间:2015-03-17 16:18:02

标签: sql oracle

在过去的几年里,我从这个社区学到了很多VBA,但现在我第一次冒险进入SQL,无法找到我需要的东西。我是自学成才,并且已经做了几天左右,需要有人帮助我学习,而不仅仅是提供解决方案。

我的目标:

创建一个查询,每个"服务订单ID输出一行" (SO_ID)并且每个" SIO Reason" (SIO_REASON)

我现在拥有的东西:

如果有多个SIO_REASON代码,则为同一SO_ID返回多行的查询。

我的代码:

我从一个包含SO_ID的表开始,然后将几个表连接到它,这样我就可以在查询中获得所需的所有信息...这里是我的代码:

    Select Distinct
a.SO_ID,
a.SERVICE_PERSON,
a.WORK_DONE_DT,
a.ACCOUNT_ID,
e.RATE_ID,
a.AREA,
d.SHORT_DESC,
d.UTIL_NAME,
b.SIO_REASON,
c.DSCR

FROM
SO_TABLE a

Left Join SERVICE_POINT_TABLE e ON
e.coy = a.coy
and e.SP_ID = a.SP_ID
and e.ACCOUNT_ID = a.ACCOUNT_ID
and (e.LINK_DT  < a.WORK_DONE_DT and (e.UNLINK_DT >= a.WORK_DONE_DT or e.UNLINK_DT = 0))

LEFT JOIN SIO_REASON_TABLE b ON
b.coy = a.coy
and b.SO_ID = a.SO_ID

LEFT JOIN SIO_REASON_DESCRIPTION_TABLE c ON
c.coy = a.coy
and b.SIO_REASON = c.SIO_REASON

LEFT JOIN AREA_TABLE d ON
d.coy = a.coy
and a.AREA = d.AREA

WHERE
a.coy = 1
and a.util_type = 'A'
and a.status = 'C'
and a.type = 'SIO'
and (a.WORK_DONE_DT >= 20150201 and a.WORK_DONE_DT <= 20150228)

ORDER BY
a.WORK_DONE_DT,
a.SO_ID,
a.SERVICE_PERSON,
a.ACCOUNT_ID,
e.RATE_ID,
a.AREA,
d.SHORT_DESC,
d.UTIL_NAME,
b.SIO_REASON,
c.DSCR

这是我得到的输出,只是一个三行示例:

SO_ID | DT | ACCT | RATE | AREA | DESC | NAME |SIO_REASON | DSCR
____________________________________________________________________
11111 |  a | 1234 | xxxx | 999  |  NE  | NEG  |    CB     | CALLBACK
11111 |  a | 1234 | xxxx | 999  |  NE  | NEG  |    FA     | FURNREPR
11111 |  a | 1234 | xxxx | 999  |  NE  | NEG  |    TM     | TIMEMATERIAL

我想要的是一条上面具有相同标题的单行(SO_ID到NAME),然后将这些标题添加到最后。对于任何给定的SO_ID,最多可以有4个SIO_REASONS,所以我想要有四个选项,如果少于4个,那么就是空出来(总是至少有一个!):

SIO1 |   DSCR1  | SIO2 |   DSCR2  | SIO3 |     DSCR3    | SIO4 | DSCR4 |
_________________________________________________________________________
 CB  | CALLBACK |  FA  | FURNREPR |  TM  | TIMEMATERIAL | null | null  |

我尽量做到尽可能详细 - 再次,我对此非常陌生,并且对子查询和类似的东西没有很好的把握。我非常愿意学习,它只是一个压倒性的东西,我不知道正确的方向去实现我想要的东西!

1 个答案:

答案 0 :(得分:1)

对于其他任何挣扎于此的人,我终于找到了适合我的解决方案!我确定它不是传统上正确的,但它完成了工作!这就是它最终看起来像:

    SELECT DISTINCT SO_ID,
  SERVICE_PERSON,
  WORK_DONE_DT,
  ACCOUNT_ID,
  RATE_ID,
  AREA,
  SHORT_DESC,
  UTIL_NAME,
  MAX(SIO_REASON_1) AS SIO_REASON_1,
  MAX(DSCR_1)       AS DSCR_1,
  MAX(SIO_REASON_2) AS SIO_REASON_1,
  MAX(DSCR_2)       AS DSCR_2,
  MAX(SIO_REASON_3) AS SIO_REASON_3,
  MAX(DSCR_3)       AS DSCR_3
FROM
  (SELECT a.SO_ID,
    a.SERVICE_PERSON,
    a.WORK_DONE_DT,
    a.ACCOUNT_ID,
    e.RATE_ID,
    a.AREA,
    d.SHORT_DESC,
    d.UTIL_NAME,
    b.SIO_REASON,
    c.DSCR,
    CASE
      WHEN b.SIO_REASON NOT IN ('CB', 'TM')
      THEN b.SIO_REASON
    END AS SIO_REASON_1,
    CASE
      WHEN b.SIO_REASON NOT IN ('CB', 'TM')
      THEN c.DSCR
    END AS DSCR_1,
    CASE
      WHEN b.SIO_REASON = 'CB'
      THEN b.SIO_REASON
    END AS SIO_REASON_2,
    CASE
      WHEN b.SIO_REASON = 'CB'
      THEN c.DSCR
    END AS DSCR_2,
    CASE
      WHEN b.SIO_REASON = 'TM'
      THEN b.SIO_REASON
    END AS SIO_REASON_3,
    CASE
      WHEN b.SIO_REASON = 'TM'
      THEN c.DSCR
    END AS DSCR_3
  FROM SO_TABLE a

Left Join SERVICE_POINT_TABLE e ON
e.coy = a.coy
and e.SP_ID = a.SP_ID
and e.ACCOUNT_ID = a.ACCOUNT_ID
and (e.LINK_DT  < a.WORK_DONE_DT and (e.UNLINK_DT >= a.WORK_DONE_DT or e.UNLINK_DT = 0))

LEFT JOIN SIO_REASON_TABLE b ON
b.coy = a.coy
and b.SO_ID = a.SO_ID

LEFT JOIN SIO_REASON_DESCRIPTION_TABLE c ON
c.coy = a.coy
and b.SIO_REASON = c.SIO_REASON

LEFT JOIN AREA_TABLE d ON
d.coy = a.coy
and a.AREA = d.AREA
  WHERE a.coy          = 1
  AND a.util_type      = 'A'
  AND a.status         = 'C'
  AND a.type           = 'SIO'
  AND (a.WORK_DONE_DT >= 20150201
  AND a.WORK_DONE_DT  <= 20150228)
  )
GROUP BY SO_ID, SERVICE_PERSON, WORK_DONE_DT, ACCOUNT_ID, RATE_ID, 
AREA, SHORT_DESC, UTIL_NAME
ORDER BY WORK_DONE_DT,
  SO_ID,
  SERVICE_PERSON,
  ACCOUNT_ID,
  RATE_ID,
  AREA,
  SHORT_DESC,
  UTIL_NAME

这给了我一个输出:

SIO1 |   DSCR1  | SIO2 |   DSCR2  | SIO3 |     DSCR3    | SIO4 | DSCR4 |
_________________________________________________________________________
 CB  | CALLBACK |  FA  | FURNREPR |  TM  | TIMEMATERIAL | null | null  |