ど素人から毛を生やす。<延>

MySQLでJOINするカラムを条件分岐させようとした話

Web > Other 2017年7月20日(最終更新:1年前)

2017年7月20日に作成されたページです。
情報が古かったり、僕が今以上のど素人だった頃の記事だったりする可能性があります。

どもです。
SQLで嵌ったので覚書。

状況としてはこんな感じ。

SELECT 
	CASE
		WHEN 条件
		THEN テーブル1.列A
		ELSE テーブル1.列B
		END  AS 列AorB
	テーブル1.列C
	テーブル2.列D
	テーブル2.列E
FROM
	テーブル1 INNER JOIN テーブル2 ON 列AorB = テーブル2.列F

FRONをSELECTで生成した仮想列にしたいわけです。
しかし、これだと「Unknown column '列AorB' in 'on clause'」というエラーを食らってしまいます。

SELECTで生成した仮想列は、FROMにまで及んでくれないのですね。

そういえば、FROMでもCASEって使えるようです。

#1
SELECT 
	省略
FROM
	テーブル1 INNER JOIN テーブル2 ON 
		(CASE
		 WHEN 条件
		 THEN テーブル1.列A
		 ELSE テーブル1.列B
		 END
		)
		= テーブル2.列F

これで解決です。

しかし、これ以外にも色々と方法があるそうで。
モノによって速度にも差が出るので、ちょっち列挙してみます。

#2
SELECT 
	省略
FROM
	テーブル1 INNER JOIN テーブル2 ON 
		( 条件   AND テーブル1.列A = テーブル2.列F )
		OR 
		( 条件の逆 AND テーブル1.列B = テーブル2.列F )

CASEを使わずとも、同じ結果を示してくれるものがありました。
どちらかというと、こっちのが見易いですかね。
デメリットは、条件の逆を書く必要があること。条件がNullならNotNullとしなければなりません。
ちょっと面倒なほか、条件が長いとミスの原因になりそうで辛い。
速度は①とほぼ同じのようです。

#3
(
	SELECT 
		省略
	FROM
		テーブル1 INNER JOIN テーブル2 ON テーブル1.列A = テーブル2.列F
	WHERE
		条件
)UNION(
	SELECT 
		省略
	FROM
		テーブル1 INNER JOIN テーブル2 ON テーブル1.列B = テーブル2.列F
	WHERE
		条件の逆
)

複数のSQLをくっつけるUNIONを使う方法。
メリットは、FROMがスッキリすること。
曰く複雑なFROMが重くなる原因だそうなので、FROM次第ではこちらの方が速くなるそうです。
デメリットは、2回SQLを実行していること。
逆にFROMがそこまで複雑でなければ、2周する分、遅くなります。

今回は、なんだかんだで①が採用されたのですが、
SELECTとFROMやWHEREはそれぞれ独立していること、
FROMやWHEREでもCASEや、サブクエリと呼ばれるものが使用できることを忘れないようにしたいと思います。

この記事は役に立ちましたか?
  • _(:3」∠)_ 面白かった (3)
  • (・∀・) 参考になった (3)
  • (`・ω・´) 役に立った (10)