質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

1回答

2449閲覧

SQLのCOUNTで0件だった場合も取得できるようにしたい

mediaquery

総合スコア1

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

0クリップ

投稿2021/07/31 14:24

前提・実現したいこと

店舗ごとの会員数、アプリ会員数を算出するSQLを書きました。
会員数、アプリ会員数両方とも1件以上ないと店舗が取得できないのですが、
本来は0件だった場合も取得できるようにしたいです。

この場合はどのように書けばよいでしょうか?PostgreSQLです。

発生している問題・エラーメッセージ

0件のデータが取れない

該当のソースコード

SQL

1select "ms"."name", COUNT(DISTINCT mc1.id) as clients_num, COUNT(DISTINCT mc2.id) as app_clients_num 2from "m_shop" as "ms" 3inner join "m_client" as "mc1" on "mc1"."shop_id" = "ms"."id" 4inner join "m_client" as "mc2" on "mc2"."shop_id" = "ms"."id" 5inner join "sales" as "sa" on "sa"."client_id" = "mc1"."id" 6where "mc2"."mobileapp" = 1 7and "sa"."settlement_date"::date >= '2021-07-01' 8and "ms"."deleted_at" is null 9group by "ms"."name";

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

内部結合(inner join)しているから、0件のデータは取得されません。
外部結合(outer join)しましょう。

SQL

1select ms.name 2 , COUNT(DISTINCT mc1.id) as clients_num 3 , COUNT(DISTINCT mc2.id) as app_clients_num 4from m_shop as ms 5 left join m_client as mc1 6 on mc1.shop_id = ms.id 7 left join m_client as mc2 8 on mc2.shop_id = ms.id 9 and mc2.mobileapp = 1 10 left join sales as sa 11 on sa.client_id = mc1.id 12 and sa.settlement_date::date >= '2021-07-01' 13where ms.deleted_at is null 14group by ms.name

※mc2への結合はmc1との結合と違いがありませんが、誤記ではないですか?
※項目名は全て小文字の様ですから、"で括るのは大文字を識別させたい時のみですので、必要はありません。

追記

SQL

1select ms.name 2 , COUNT(mc.id) as clients_num 3 , COUNT(case when mc.mobileapp = 1 then mc.id end) as app_clients_num 4from m_shop as ms 5 inner join sales as sa 6 on sa.client_id = ms.id 7 left join m_client as mc 8 on mc.shop_id = ms.id 9where ms.deleted_at is null 10 and sa.settlement_date::date >= '2021-07-01' 11group by ms.name

投稿2021/07/31 16:28

編集2021/08/01 04:12
sazi

総合スコア25206

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mediaquery

2021/08/01 02:13

ご丁寧にありがとうございます。 理想にだいぶ近い形で取得できました。 > ※mc2への結合はmc1との結合と違いがありませんが、誤記ではないですか? 今回同じテーブルから違う条件でCOUNTするためにmc1とmc2を結合しました。 `mc2.mobileapp = 1` があることで、この条件のCOUNTが取れるのかなと思い。 他に書き方があれば知りたいです。 > ※項目名は全て小文字の様ですから~~~ ありがとうございます。仰る通りでした。 またご教授いただいたSQLで取得しましたが、 `clients_num` については、 `and sa.settlement_date::date >= '2021-07-01'` この条件が効いてないような挙動が見られました。これはleft joinでNULLでも結合されているからでしょうか?
sazi

2021/08/01 04:08 編集

> `mc2.mobileapp = 1` があることで、この条件のCOUNTが取れるのかなと思い、他に書き方があれば知りたいです。 count()の際に条件判定するのが良いかと思います。 > `clients_num` については、 `and sa.settlement_date::date >= '2021-07-01'` この条件が効いてないような挙動が見られました。 結局、m_shop に対する条件となるようなので、m_shop とinner join するのが効率的ですね。
mediaquery

2021/08/01 13:24

ご丁寧にありがとうございました。 無事解決することができました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問