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

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

ただいまの
回答率

89.99%

グループ内で条件に当てはまらないレコードを持つグループを取得したい

解決済

回答 2

投稿 編集

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

meg278

score 5

MySQLを使用しています。
以下のテーブルで、
提出日または入力日が指定期間内(2019/04/01~2020/03/31)のデータを持たない
会社コード、社員コードを抽出したいです。

テーブル T1

会社コード 社員番号 連番 提出日 入力日
AAA 0001 1 2018-03-20 2018-03-30
AAA 0001 2 2019-04-10 NULL
AAA 0002 1 2019-03-10 NULL
AAA 0003 1 2019-04-10 2019-04-15
BBB 0004 1 2019-03-10 NULL
BBB 0004 2 NULL 2018-03-30

上記の例では

会社コード 社員番号
AAA 0002
BBB 0004

の取得を実現したいです。

次のようなSQLを考えましたが期待する結果が取れません。

select 会社コード,社員番号 from T1 
  where 
   ((提出日 >= '2019-04-01' and 提出日 < '2020-04-01') or
          (入力日 >= '2019-04-01' and 入力日 < '2020-04-01'))
  group by 会社コード,社員番号 having count(*) =0

追記です。
社員番号はAAA社にもBBB社にも同じ番号のレコードが存在し、会社コード+社員番号でユニークです。
以下create table文となります。

CREATE TABLE `T1` (
  `会社コード` varchar(3) NOT NULL,
  `社員番号` varchar(5) NOT NULL,
  `連番` smallint(2) NOT NULL,
  `提出日` date DEFAULT NULL,
  `入力日` date DEFAULT NULL,
  PRIMARY KEY (`会社コード`,`社員番号`,`連番`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;


どうぞよろしくお願いいたします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • yambejp

    2019/05/09 12:47 編集

    ・社員番号は全体でユニークなのでしょうか(A社、B社にまたがって)
    ・それともA社に1番がいてもB社にも1番がいるのでしょうか?
    上記条件で処理が違います

    できれば属性をきちんと配慮したcreate tableで提示していただけると助かります

    キャンセル

  • meg278

    2019/05/09 13:20

    説明が足りず申し訳ありません。情報を追記いたしました。よろしくお願いいたします。

    キャンセル

回答 2

+2

「存在しない」ものを探す場合、NOT EXISTSを使うと良いと思います(EXISTSが「存在する」で、それの否定形(NOT)なので「存在しない」ものを探します)。

https://www.sejuku.net/blog/73615#NOT_EXISTS

動作は検証していませんが、サンプルコードです。

SELECT DISTINCT -- 同一の会社コードと社員コードの組み合わせがたくさん出てこないようにDISTINCTします
    a.会社コード,
    a.社員コード
FROM
    T1 AS a
WHERE
    NOT EXISTS (
        SELECT
            *
        FROM
            T1 AS b
        WHERE
            (
                -- aテーブルとbテーブル(実体は同じテーブルですが、a=検索対象テーブル、b=除外対象を示すテーブル)の結合条件。今回は、「除外条件に該当するデータが存在しない」会社コードと社員コードが抽出したいので、会社コードと社員コードを結合条件に指定します。
                a.会社コード = b.会社コード
                AND
                a.社員番号 = b.社員番号
            )
            AND
            (
                -- 除外条件。ここではbテーブルのカラムだけを指定します
                b.提出日 BETWEEN '2019/04/01' AND '2020/03/31'
                OR
                b.入力日 BETWEEN '2019/04/01' AND '2020/03/31'
            )
    )

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/05/09 14:09

    回答ありがとうございます。期待する結果を得ることができました!
    丁寧な解説までいただき助かりました。ありがとうございました。

    キャンセル

  • 2019/05/09 14:15

    NOT EXISTS を使った例も非常にわかりやすかったのですが、今回はSQLがよりすっきりしていたyambejp様の回答をベストアンサーにさせていただきたいと思います。お忙しいところ素早い回答をいただき非常に助かりました。ありがとうございました。

    キャンセル

checkベストアンサー

+1

nakさんの回答が良いと思いますが、あえて別解釈

select 会社コード,社員番号 from T1
group by 会社コード,社員番号
having coalesce(sum(
提出日 between '2019/04/01' and '2020/03/31'
or 入力日 between '2019/04/01' and '2020/03/31'
),0)=0

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/05/09 13:48 編集

    回答いただきありがとうございます。having句の
    coalesce(sum(
    提出日 between '2019/04/01' and '2020/03/31'
    or 入力日 between '2019/04/01' and '2020/03/31'
    ),0)=0
    の部分が理解ができないのですが、
    「提出日が期間内、または入力日が期間内のデータ件数が0件」
    ということでしょうか?いまいち腑に落ちていないので解説をお願いできますでしょうか。
    追記:結果は期待する結果が取得できました!自分の理解が追いついておらずすみません。。

    キャンセル

  • 2019/05/09 13:59 編集

    sumを取ると0件の場合とnullの場合が混在することがあります
    nullだったときに0と読み替えるのがcoalcaseです
    SQLにおいてnullは非常に特殊な挙動をとりますので、
    今回に限らず取扱に注意ください
    たとえばnullは指定させず、過去日(1970-01-01)や未来日(2099-12-31)などを
    指定するなどの方が管理は楽になる場合があります

    キャンセル

  • 2019/05/09 14:16

    coalcaseの使い方を初めて知りました。勉強になりました。ありがとうございます。nullについても今後注意していきたいと思います。お忙しいところ回答いただきありがとうございました。

    キャンセル

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

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