SQLのGREATEST関数とLEAST関数を使ってみる

こんにちは!kossyです!




今回はSQLのGREATOR関数とLEAST関数を使って、MAXやMINとの挙動の違いを調査してみたいと思います。



環境

Ruby 2.6.6
Rails 6.0.3.7
MacOS catalina



GREATESTとLEAST関数

www.postgresql.jp

GREATESTとLEAST関数は任意の数の式のリストから最大値もしくは最小値を選択します。 評価される全ての式は共通の型に変換できる必要があり、それが結果の型になります(詳細は10.5を参照してください)。 リストの中のNULL値は無視されます。 全ての式がNULLと評価された場合に限って結果はNULLになります。


GREATESTおよびLEASTはSQL標準に載っていませんが、共通した拡張です。 他のいくつかのデータベースでは、全てがNULLの場合に限定せず、いずれかの引数がNULLである場合にNULLを返すようにしているものもあります


出典: 9.17. 条件式

LEAST関数で「任意の数の式のリスト」をコードで雑に現してみます。

    query = <<-SQL.squish
      SELECT LEAST(created_at, updated_at, hired_at, retired_at) as least_date
      FROM employees
      LIMIT 10
    SQL

上記のようにQueryを走らせると、式のリストの中で最小の値を求めることができます。

実運用だと、「複数の日程の中で期日が一番近い日付が欲しい時」や、「いくつかの価格の中で最安値が知りたい時」等で使えると思います。

MAX・MIN関数との比較

database.guide

上記ドキュメントにも記載がありますが、GREATEST(LEAST) と MAX(MIN)関数では受け取る引数が異なります。

    # 以下SQLだとエラーになる

    query = <<-SQL.squish
      SELECT MIN(created_at, updated_at, hired_at, retired_at) as least_date
      FROM employees
      LIMIT 10
    SQL

    ActiveRecord::StatementInvalid: PG::UndefinedFunction: ERROR:  function min(timestamp without time zone, timestamp without time zone, date, date)

MAX(MIN)関数は複数のレコードを照会して、最大(最小)のレコードを引いてくる動作をします。このため、複数の引数をMAX(MIN)関数に渡すと例外となるわけです。

    query = <<-SQL.squish
      SELECT MAX(hired_at) as max_date
      FROM employees
    SQL

上記のQueryだとemployees(従業員)テーブルの中で、入社日が一番若い日付が取得できます。

まとめ

GREATEST(LEAST)関数ともにSQL標準ではないのは知らなかったです。
どちらも便利なSQL関数かと思いますので、使いこなせるように日々勉強です。