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

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

ただいまの
回答率

89.19%

列ごとに日付を持ち、ある条件を満たす日付のみ取得したい。

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 414

fjaiofjawiefjaw

score 164

下記の様に、テーブルとデータを作成します。

CREATE TABLE `sample_table` (
  `id` int NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `date` date NOT NULL,
  `number` int(11) NOT NULL
);

INSERT INTO `sample_table` (`date`, `number`)
VALUES ('2018-08-01', '1');
INSERT INTO `sample_table` (`date`, `number`)
VALUES ('2018-08-01', '2');
INSERT INTO `sample_table` (`date`, `number`)
VALUES ('2018-08-01', '3');
INSERT INTO `sample_table` (`date`, `number`)
VALUES ('2018-08-02', '1');
INSERT INTO `sample_table` (`date`, `number`)
VALUES ('2018-08-02', '2');
INSERT INTO `sample_table` (`date`, `number`)
VALUES ('2018-08-03', '1');
INSERT INTO `sample_table` (`date`, `number`)
VALUES ('2018-08-03', '3');
INSERT INTO `sample_table` (`date`, `number`)

dateカラムとnumberカラムの対応を見た場合、
2018-08-01は、numberカラムの値、1,2,3を全て持ちます。
しかし、
2018-08-02は、1,2のみ
2018-08-03は、1,3のみ
つまり、全てを持っていません。

この全てを持っていない
2018-08-02と2018-08-03
を表示することは、可能でしょうか。
可能な場合、
どのような構文を利用すればいいのでしょうか?
※そもそも、table構造的に無理なのかもしれないと思っております。

自身で書いたsql文(申し訳ありません、自身では、まったく思いつきませんでした。)

SELECT date
FROM sample_table
WHERE date between '2018-08-01' AND '2018-08-31'
GROUP BY date
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+2

SELECT `date` FROM sample_table
WHERE `date` NOT IN (
    SELECT `date` FROM sample_table
    GROUP BY `date`
    HAVING count(DISTINCT `number`) = 3
) 
GROUP BY `date`

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/08/19 06:28 編集

    ご回答ありがとうございます。
    非常に早い回答、誠にありがとうございます。
    sqlの一つ一つの構文は、サラッと見た程度で分かった気になっておりましたが、
    回答のようなテクニカルなsql文(しかもこの短時間で)は、見たことがありませんでした。
    もう少し、勉強、頑張りたいと思います。ありがとうございました。

    追記(2018/08/20/02:38)
    自身の今後の勉強のために
    見返すかもしれませんので、長文失礼いたします。
    以下、自身の解釈です。

    まず、サブクエリ内で
    dateをグループ化する。
    その各dateグループに対して、
    numberカラムの重複を削除した個数をカウントする。
    ※1と2と3、全てある場合は、3個。
    having句により、個数が、3個の場合のグループを抽出する。
    つまり、サブクエリで得られるものは、
    1と2と3を全て含むdate値ということ。

    メインクエリ内では、
    where句により
    サブクエリから得た
    1と2と3を全て含むdate値群のどれとも合致しない
    つまり、
    1 AND 2 AND 3
    の逆は、
    1でない OR 2でない OR 3でない
    なので、
    1と2と3の内、(0個)or1個or2個を含む
    date値を取得。
    ※0個の場合が存在することは、ベン図をイメージしたら
    分かりました。
    しかし、0個は、numberカラムの値を外部キーなどで1,2,3に縛る。
    かつ、nullを禁止すれば無くせるため、
    今回は、1個or2個として機能する。

    sazi様との回答の違いとしては、
    sazi様のsql文は、メインクエリ内で、ダイレクトに求めるもので
    今回の場合は、サブクエリで逆の条件のものを求め、それの否定を得るものであると認識させて頂きました。
    大変勉強になりました。ありがとうございます。

    キャンセル

+2

date別のnumberの要素数と全体での要素数を比較します。

select date FROM sample_table group by date
having count(distinct number) !=(select count(distinct number) from sample_table)


全体の要素数が予め決まっているなら以下のように記述できます。

select date FROM sample_table group by date
having count(distinct number) !=3

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/08/19 06:46

    ご回答ありがとうございます。
    countがなぜ、集約関数と呼ばれているか、少しは理解できた気がします。
    しかし、グループ化のイメージがまだよく頭の中で出来ていないので、完璧には理解できませんでした。
    sql文のグループ化を利用する中で、勉強していきたいと思います。

    キャンセル

  • 2018/08/19 07:11

    説明的に追記しました。

    キャンセル

  • 2018/08/19 17:35 編集

    追記の方、確認させて頂きました。
    ありがとうございます。

    以下、自分なりの解釈です。
    あるカラムをグループ化することにより、同一の特徴を持ったもの同士の各グループに分けることができる。
    名称が正しいか不明ですが、グループ関数(countやdistinct)?は、上記で作られた各グループに対して実行される。
    distinctでnumberカラムの重複を排除し、それをcountでカウントする。
    ご回答頂いた、2個目のsqlの要素数とは、今回のnumberカラムの数を表しており、1と2と3の3個ということですね。

    大変、勉強になるsqlでした。
    ありがとうございました。

    キャンセル

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

  • ただいまの回答率 89.19%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる