1
1

More than 3 years have passed since last update.

CASE式を使って検索項目が空欄の場合に条件を無視する

Last updated at Posted at 2020-11-25

if文を使わず、SQLのCASE式でnullを無視した検索を実行する

以下のような形で検索に使用する入力項目がいくつもあった場合に、コントローラー側でif文を使って空欄時とそうでないときの場合分けをするとif/elseがずらーっと並ぶ上、同じようなメソッドをいくつも使ってコードが汚くなるので、SQLでどうにかできないかといろいろ調べてみたところ、SQLのCASE式を使えばif文を使わずに、よりスマートにコードがかけることがわかったので備忘録として残します。
スクリーンショット 2020-11-25 20.12.23.png

repository.java
    @Query(value = "SELECT * FROM mst_asset" 
                 + " WHERE id = CASE WHEN :id = 0 THEN id ELSE :id END" 
                 + " AND category_id = CASE WHEN :categoryId = 0 THEN category_id ELSE :categoryId END" 
                 + " AND admin_name LIKE concat('%', CASE WHEN :adminName = '' THEN admin_name ELSE :adminName END, '%')"
                 + " AND asset_name LIKE concat('%', CASE WHEN :assetName = '' THEN asset_name ELSE :assetName END, '%')" 
                 + " AND delete_flag = false ORDER BY id ASC"
                 +  , nativeQuery = true)
    List<Asset> findByIdAndCategoryIdAndAdminNameAndAssetName(
        @Param("id") Integer id,
        @Param("categoryId")Integer categoryId,
        @Param("adminName") String adminName,
        @Param("assetName") String assetName);

どうやら、WHERE句の[カラム名]=[カラム名]の場合には条件としてカウントしないという性質があるらしくそれを、CASE式に応用することで画面で検索キーワードが入力されなかったパラメータを無視してSQLを実行することができるらしい。
上記のコードでは、Integer型の入力欄のパラメーターに関しては空欄のままだとnullとして受け取ってしまうので、その場合はサービスの中でif文を使って0にセットしてます。String型のパラメーターに関しては、入力された際にはそれをサービスの中でトリミングしてconcatを使って部分一致検索にしてます。

1
1
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1