複数のcount()の結果を四則演算

SQLにおいて表題のことをやりたかった。

■ 環境

  • Amazon Athena

■ count()

単純に”count()“の結果を計算するのであれば特に問題なくできるのだが、1つのクエリで複数の”count()“を実行し、その結果を使って四則演算したかった。

SELECT
  regist_date,
  count(1) as total,
  count(column1 < 10 or null) as count1, count(column1 >= 10 or null) as count2
FROM testtable
GROUP BY regist_date

以前使用した上記のSQLであれば、下記のようなことを行いたい。

count1 + count2

これを一度のクエリでは書けないので下記のようにすれば一応実行はできる。

SELECT regist_date, total, count1 + count2 as count3
FROM (
  SELECT
    regist_date,
    count(1) as total,
    count(column1 < 10 or null) as count1, count(column1 >= 10 or null) as count2
  FROM testtable
  GROUP BY regist_date
)

まぁ確かにできるのだがもっとスマートな書き方はないのかな。

以上。

■ 関連

複数条件のcount()

count(distinct (case when … then … end))

SQLにおいて表題の件。自身はAthenaでとても重宝した。条件に合致した中での一意な数を取得したい。

■ 環境

  • Amazon Athena

■ count(distinct)

Athenaを利用しているので、読み込むデータ量も減らしたいしクエリを実行する対象は減らしたい。なので1回のクエリ実行で必要な情報を得たい。複数の条件で`count()`を取得したいが、これは以前のエントリで述べた通り。今回はさらに条件を絞った状態で`distinct`の値を取得したかった。

SELECT
  regist_date,
  count(1) as total,
  count(column1 < 10 or null) as count1, count(column1 >= 10 or null) as count2,
  count(distinct groupid) as group_count1,
  count(distinct (case when column1 < 10 then groupid end)) as group_count2, count(distinct (case when column1 >= 10 then groupid end)) as group_count3,
FROM testtable
GROUP BY regist_date

上記のようなSQLにすることで1度のクエリ実行で自身が得たいデータは全て取得できるようになった。

group_count1“は全体における”groupid“の`distinct`の値。一意な`groupid`の数を取得できる。

group_count2“は、`column1 < 10`の条件に合致した中での一意な`groupid`の数を取得できる。

group_count3“は…以下略。

以上。

■ 関連

複数条件のcount()

S3ライフサイクル

表題の件でゴミを削除することにした。

■ 環境

  • AWS S3

■ ライフサイクル

ライフサイクルでは、一定期間経過後、オブジェクトをGlacierに移動させたりすることができる。今回は該当バケット内に作成された全てのオブジェクトを対象に、作成されて1週間以上経過後のオブジェクトを破棄するようにした。Management Consoleから設定を行ってみる。

該当のバケットを表示後、上部の”管理“より”ライフサイクルルールの追加“を実施する。

ルール名は自身が判別つくわかりやすいもので構わない。フィルターは今回は使用していないが、該当のprefix配下のオブジェクトのみが対象である場合にはここで指定する。

今回はGlacierへの移行ではないのでここはスキップする。

現行バージョン“のみチェックしている。これは該当のバケットではバージョン設定を使用していないからである。”オブジェクトの現行バージョンを失効する“にチェックを入れ、日数は”7“としている。”不完全なマルチパートアップロードをクリーンアップする“も一応チェックを入れておいた。日数はデフォルトままの”7“である。

最後は内容を確認し保存して完了である。

実行されるタイミングはよくわからないが、新たなオブジェクトを追加したタイミングとかであろうか。まぁ自身にとっては不要なファイルを削除してほしいだけなので実行されるタイミングはなんであろうと問題ない。

以上。

CONCAT & CAST & LPAD

Amazon Athenaで表題の関数について。Amazon Athenaに限った話ではなくSQLの話だけれども…。

■ 環境

  • Amazon Athena

■ きっかけ

やりたいこととしては単純に『カラムの値を連結したい』ということだけのはずだった。もうずっと単純なSQLしか書いていなかったのでここら辺の関数についていろいろ忘れておりはまってしまった。

■ CONCAT

文字列として連結したいんだから、”CONCAT“でいけるだろうと思い試してみたところ、下記のエラーが出た。

Error running query: SYNTAX_ERROR: line 1:185: Unexpected parameters (integer) for function concat. Expected: concat(array(E), E) E, concat(E, array(E)) E, concat(array(E)) E, concat(varchar)

あれ?と思いドキュメントを見ていると下記を発見。

Concatenating Arrays
https://docs.aws.amazon.com/ja_jp/athena/latest/ug/concatenating-arrays.html

いややりたいことは”文字列“としての連結であって、配列の連結ではない。ということでこれは違う。もう一度エラーメッセージをよく見てみると下記の通り。

concat(varchar)

できるはずである。としばし考えて気がついた。対象のカラムの型が”int“であった。では”CAST“を挟めば良いのか。ということで下記のような感じになった。

select concat(cast(year as varchar), cast(month as varchar), cast(day as varchar)) ...

しかし得られた結果がこれでは微妙であった。”2018316“。”0“パディングしなければならない。”LPAD“の出番である。”LPAD“だから戻ってくるのは”varchar“だよね、と思い下記のように書き換えた。

select concat(cast(year as varchar), lpad(month, 2, '0'), lpad(day, 2, '0')) ...

実行すると下記のようなエラーが…。

Error running query: SYNTAX_ERROR: line 1:215: Unexpected parameters (integer, integer, varchar(1)) for function lpad. Expected: lpad(varchar(x), bigint, varchar(y))

これもエラーログをよく読んでみれば解決した。ここも”CAST“が必要であった。

最終的に下記で思い通りの結果を得られた。

select concat(cast(year as varchar), lpad(cast(month as varchar), 2, '0'), lpad(cast(day as varchar), 2, '0')) ...

以上。

aws route53 get-hosted-zone

先日に続いて表題のコマンドについて。

■ 環境

  • awscli 1.14.50
  • Mac OSX El Capitan

■ route53 get-hosted-zone

Hosted zone“の詳細を取得する。`get-hosted-zone`には必須オプションで”–id“が必要であるので、先日の`list-hosted-zones`で得られるIDを用いる。

$ aws route53 list-hosted-zones
  :
$ aws route53 get-hosted-zone --id /hostedzone/XXXXXXXXXXXXXX
{
    "HostedZone": {
        "Id": "/hostedzone/XXXXXXXXXXXXXX",
        "Name": "withsin.com.",
        "CallerReference": "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX",
        "Config": {
            "PrivateZone": false
        },
        "ResourceRecordSetCount": 12
    },
    "DelegationSet": {
        "NameServers": [
            "ns-XXX.awsdns-XX.net",
            "ns-XXX.awsdns-XX.org",
            "ns-XXX.awsdns-XX.com",
            "ns-XXX.awsdns-XX.co.uk"
        ]
    }
}

ここで得られた”NameServers“をドメインを取得した管理元に設定する。

以上。

■ 関連

aws route53 list-hosted-zones