ゆるふわエンジニアのブログ

行ったこと、調べたこと等をつらつらと書いていくかもしれません。

SQL文を駆使し、縦持ちのデータを横持ちにする+α(Oracle)

SQL文を駆使し、縦持ちのデータを横持ちにする方法について書いていきます。

お仕事で、
「この縦持ちデータを横持ちにして見やすくしたいね~」
といったことを言われることがあります。

下記のデータを元に、どうSQLを書けばいいのか見ていきましょう。

KENNIN_IRAI_NO KENNIN_JUN KENNINSHA_MEI KENNIN_SUMI_KUBUN
20160821 1 TANAKA 1
20160821 2 SUZUKI 0
20160821 3 NAKAMURA 0
20160822 1 KONDO 1
20160822 2 TANAKA 1
20160822 3 NAKAMURA 1
20160822 4 HAYASHI 0
20160823 1 SHIMA 1
20160823 2 TANAKA 1

上記データは、左から
検認依頼番号、検認を行う順番、検認者名、
検認済かどうかを表す区分(0なら未検認、1なら検認済)を表しています。

検認検認番号毎に、検認を行う順番で左から検認者名を表示してみましょう。
そういったことを行うには、下記の様なSQL文を使用すると実現できます。

SELECT
   A.KENNIN_IRAI_NO
  ,MAX(CASE
         WHEN A.KENNIN_JUN = 1 THEN A.KENNINSHA_MEI
          ELSE NULL
       END) AS KENNINSHA_MEI1
  ,MAX(CASE
         WHEN A.KENNIN_JUN = 2 THEN A.KENNINSHA_MEI
         ELSE NULL
       END) AS KENNINSHA_MEI2
  ,MAX(CASE
         WHEN A.KENNIN_JUN = 3 THEN A.KENNINSHA_MEI
         ELSE NULL
       END) AS KENNINSHA_MEI3
  ,MAX(CASE
         WHEN A.KENNIN_JUN = 4 THEN A.KENNINSHA_MEI
         ELSE NULL
       END) AS KENNINSHA_MEI4
FROM
  KENNIN_IRAI_TBL A
GROUP BY
  A.KENNIN_IRAI_NO
ORDER BY
  A.KENNIN_IRAI_NO ASC

どの項目毎に横持ちでデータを表示させたいかをGROUP BYで指定し、
後はSELECTで集計関数を使用し各検認順毎にデータが存在していれば表示、
していなければ非表示、ということをしています。

結構応用が効くので、覚えておいて損は無いと思います。


さて、ここからはおまけ(という名の本編)です。
上記から派生して、
「横持ちで表現できるなら、縦持ちデータを元に進捗バーみたいな表現が出来ればわかりやすいよね(チラッチラッ」
といった要望が出ることも稀によくあります。
そういった場合は、下記の様にMAX関数内で使用しているCASE文に条件を追加してやります。

SELECT
   A.KENNIN_IRAI_NO
  ,MAX(
       CASE
         WHEN A.KENNIN_JUN = 1 AND A.KENNIN_SUMI_KUBUN = '1' THEN '●'
         WHEN A.KENNIN_JUN = 1 AND A.KENNIN_SUMI_KUBUN = '0' THEN '○'
         ELSE NULL
       END
      ) AS KENNIN_STATUS1
  ,MAX(
       CASE
         WHEN A.KENNIN_JUN = 2 AND A.KENNIN_SUMI_KUBUN = '1' THEN '●'
         WHEN A.KENNIN_JUN = 2 AND A.KENNIN_SUMI_KUBUN = '0' THEN '○'
         ELSE NULL
       END
      ) AS KENNIN_STATUS2
  ,MAX(
       CASE
         WHEN A.KENNIN_JUN = 3 AND A.KENNIN_SUMI_KUBUN = '1' THEN '●'
         WHEN A.KENNIN_JUN = 3 AND A.KENNIN_SUMI_KUBUN = '0' THEN '○'
         ELSE NULL
       END
      ) AS KENNIN_STATUS3
  ,MAX(
       CASE
         WHEN A.KENNIN_JUN = 4 AND A.KENNIN_SUMI_KUBUN = '1' THEN '●'
         WHEN A.KENNIN_JUN = 4 AND A.KENNIN_SUMI_KUBUN = '0' THEN '○'
         ELSE NULL
       END
      ) AS KENNIN_STATUS4
FROM
  KENNIN_IRAI_TBL A
GROUP BY
  A.KENNIN_IRAI_NO
ORDER BY
  A.KENNIN_IRAI_NO ASC

検認済なら●を、未検認なら○を、検認者が設定されていなければ
何も表示しないようにしています。

他には、縦持ちデータに別の縦持ちデータを横持ちでくっつけて(数は可変)
2次元表を作り、それをExcel形式で出力したいとかも稀によくありますね。
そういった要望に応えられるよう、覚えておくと良いと思います。