Rainbow Engine

IT技術を分かりやすく簡潔にまとめることによる学習の効率化、また日常の気付きを記録に残すことを目指します。

Database (データベース) OracleDB SQL

SQLでCASE文の結果をWHERE句に指定する方法およびコスト面の考察

投稿日:2019年9月16日 更新日:

本記事では、
・SQLでCASE文の結果をWHERE句に指定する方法について記述します。
・CASE文を使う場合のコストについて考察します。

(0)目次&概説

(1) NG例
(2) OK例&解説
(3) CASE文の性能考察
 (3-1) UNIONで書いた時コスト
 (3-2) CASEで書いた時のコスト
 (3-3) 考察

(1) NG例

例えば「EMP」表と「DEPT」表の結合を例に考えてみます。
EMP表(TA)はCASE文で「SAL」カラムの多い少ないに応じて「HIGH SAL」または「LOW SAL」の値を動的に取得しています(例文1の4~7行目)
DEPT表(TB)は「DEPTNO」カラムでEMP表(TA)と結合(例文1の13行目)しています。

そしてここからが本題で、CASE文で取得した「SALARY」(別名)をWHERE句に使いたい場合です。(例文1:14行目)のように指定するとエラーになります(※「結局HIGHで絞るならCASE文いらなくね?」というツッコミもあると思いますが、まあ例なので・・笑)

(例文1)※構文エラー

SELECT
  --CASE文で下記のルールで値を動的に取得
  --SALが40万以上なら「HIGH SAL」/40万未満なら「LOW SAL」
  CASE
    WHEN TA.SAL > 400000 THEN 'HIGH SAL'
    WHEN TA.SAL < 400000 THEN 'LOW SAL'
  END AS SALARY
  ,TA.*
  ,TB.*
FROM 
  EMP TA
  ,DEPT TB
WHERE	TA.DEPTNO = TB.DEPTNO
AND 	SALARY = 'HIGH SAL'

(例文1)エラー

(2) OK例&解説

このエラーを回避するためにFROM句にテーブルをそのまま指定するのではなく、SELECT文の形で指定します。具体的には次の(例文2)の5行目~15行目のように、抽出データの加工はSELECTの部分ではなくFROMの部分で行っています。そうする事でWHERE句等でも指定が可能となります。

 (例文2)OK例

SELECT
  TA.*
  ,TB.* 
FROM
 (
  SELECT
	--CASE文で下記のルールで値を動的に取得
	--SALが40万以上なら「HIGH SAL」/40万未満なら「LOW SAL」
	CASE
	  WHEN E.SAL >= 400000 THEN 'HIGH SAL'
	  WHEN E.SAL < 400000 THEN 'LOW SAL'
	END AS SALARY
	,E.*
  FROM EMP E
 ) TA
,DEPT TB
WHERE	TA.DEPTNO = TB.DEPTNO
AND 	SALARY = 'HIGH SAL'


 (例文2)結果

目次にもどる

(3) CASE文の性能考察

次に性能面での考察を少し行います。今回の例は「EMP」表から「HIGH SAL」と「LOW SAL」の人数をそれぞれ出力するSQLを2通りのやり方で記述し、それぞれの「コスト」と比較を行います。

(3-1) UNIONで書いた時コスト

UNIONで書いた場合のコストは「917」で、実行時間が「0.049秒」でした。構造は、前半の「HIGH SAL」抽出SQLと後半の「LOW SAL」抽出SQLを単純にUNIONしているだけです。
(例文3)

-- ①'HIGH SAL'のデータを抽出するSQL
SELECT
  'HIGH SAL' AS SALARY
  ,COUNT(*)
FROM
	EMP TA
	,DEPT TB
WHERE	TA.DEPTNO = TB.DEPTNO
AND   TA.SAL >= 400000

--①と②を合わせる
UNION

-- ②'LOW SAL'のデータを抽出するSQL
SELECT
  'LOW SAL' AS SALARY
  ,COUNT(*)
FROM
	EMP TA
	,DEPT TB
WHERE	TA.DEPTNO = TB.DEPTNO
AND   TA.SAL < 400000

(例文3)結果

(3-2) CASEで書いた時コスト

CASEで書いた場合のコストは「459」で、実行時間が「0.069秒」でした。細かい部分は違えど、構造は(例文2)と同じです。
(例文4)

SELECT
  SALARY
  ,COUNT(SALARY)
FROM
	(
	  SELECT
		CASE
		  WHEN E.SAL >= 400000 THEN 'HIGH SAL'
		  WHEN E.SAL < 400000 THEN 'LOW SAL'
		END AS SALARY
		,E.*
	  FROM EMP E
	) TA
	,DEPT TB
WHERE	TA.DEPTNO = TB.DEPTNO
GROUP BY SALARY
ORDER BY SALARY

(例文4)結果

(3-3) 考察

CASEを使った方がUNIONよりもコスト(リソース消費)が抑えられたが、実行時間はUNIONの方が速かったため、必ずしもどちがら良いとは断言できず、環境のリソース状況や要件によってどのアプローチが最善かを検討する形になると考えます。

 >目次にもどる

Adsense審査用広告コード


Adsense審査用広告コード


-Database (データベース), OracleDB, SQL

執筆者:


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

関連記事

JavaのJDBC接続でjava.sql.SQLRecoverableException: Closed Connectionが発生した時の解決メモ

(0)目次&概説 (1) エラー事象の概要  (1-1) エラーの発生状況  (1-2) エラーメッセージ全文 (2) エラーの原因 (3) エラーの対処方法  (3-1) エラーの修正内容  (3- …

インピーダンスミスマッチとは?を分かりやすく説明

<目次> (1) インピーダンスミスマッチとは?を分かりやすく説明  (1-1) 概要  (1-2) 具体例 (1) インピーダンスミスマッチとは?を分かりやすく説明 (1-1) 概要 「インピーダン …

論理テーブル設計と物理テーブルデータ設計の違いや特徴

  <目次> (1) 論理テーブル設計と物理テーブルデータ設計の違いや特徴  (1-1) 論理テーブル設計とは?  (1-2) 物理テーブル設計とは?  (1-3) 両者の違い (1) 論理 …

OracleDBのメディア障害やインスタンス障害からの復旧について

(0)目次&概説 (1) 障害復旧について  (1-1) インスタンス障害  (1-2) メディア障害   (1-2-1) 制御ファイル   (1-2-2) REDOログファイル   (1-2-3) …

OracleDB11gのキャラクタセットを変更する手順について(概要編)

(0)目次&概説 (1) 記事の目的  (1-1) 目的  (1-2) 前提条件   (1-2-1) 「props$」更新はNG   (1-2-2) 10g以降は”ALTER DATABA …

  • English (United States)
  • 日本語
Top