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

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

ただいまの
回答率

90.50%

  • SQL

    2394questions

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

【SQL】  ある条件の下でMAX値を取得したい

解決済

回答 3

投稿 編集

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

matsutake

score 12

SQL文で困っております。

下記のようなデータがあった場合に、
IDごとにデータをそれぞれチェックし、
購入日の最大値が2017年12月31日より前の購入日のデータを取得したい場合、
どのようなSQL文で取得できるのでしょうか。
色々と試しているのですが、
ID:1は本来は取得対象外にしたいのですが、
2017年5月7日のデータを取得してしまうのです。

<検索対象データ>
テーブル名:購入履歴テーブル

フィールド名:
ID    購入日

1        2018年4月9日
1        2017年5月7日
1        2016年4月11日
2        2015年6月10日
2        2014年4月9日
2        2013年4月11日
3        2017年5月6日
3        2016年4月7日
3        2014年8月11日

<自分で書いたSQL文で取得したデータ>
ID    購入日

1        2017年5月7日(※取得したくない)
2        2015年6月10日
3        2017年5月6日

<取得したいデータ>
ID    購入日

2        2015年6月10日
3        2017年5月6日
宜しくお願いします。

上記の内容では不足しておりましたので、追記いたします。
自分で書いたSQL文は以下になります。

CREATE TABLE [購入履歴] (
    [ID] [int] NOT NULL PRIMARY KEY,
    [BuyDate] [varchar(14)] [NOT NULL]
    );
SELECT ID, MAX(購入日) AS 購入日
FROM 購入履歴テーブル
GROUP BY ID
HAVING 購入日 < '2017-12-31'
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • matsutake

    2018/05/08 17:16

    saziさん。ご指摘の通りです。申し訳ござませんでした。

    キャンセル

  • sazi

    2018/05/08 17:19

    謝る必要は無いですよ。訂正すればいいだけですし。で、DBMS(oracleだとかMySQLだとか)の明示もお願いしますね。

    キャンセル

  • matsutake

    2018/05/08 17:27

    ご丁寧にありがとうございます。SQL Serverになります。

    キャンセル

回答 3

checkベストアンサー

+2

こんなかな?

SELECT ID, MAX(購入日) AS 最終購入日
FROM 購入履歴テーブル
GROUP BY ID
HAVING MAX(購入日) < '2017-12-31'

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/05/08 17:32

    hihijijiさん。
    ありがとうございました。
    HAVING句内の部分でMAXがない状態で「購入日」と書いており、
    更にその「購入日」をGROUP BY句に入れてしまっていた結果、
    MAX値が出ないで指定した日付より以前のデータが
    全て抽出されるようなことになっておりました。
    本当に助かりました。
    ありがとうございました。

    キャンセル

+1

どんなテーブルなのかはCREATE TABLEで簡潔に提示できます。
どんなデータがあるかもINSERT文で提示しましょう。

<自分で書いたSQL文で取得したデータ>

も提示するのが掲示板ではマナーです。

Oracleですと、

CREATE TABLE KOKYU_RIREKI
    (
    ID      NUMBER(1) NOT NULL
  , KONYUBI DATE      NOT NULL
  , CONSTRAINT PK_KOKYU_RIREKI PRIMARY KEY(ID, KONYUBI) USING INDEX
    ) ;
INSERT INTO KOKYU_RIREKI(ID, KONYUBI) VALUES(1, TO_DATE('2018/04/09', 'YYYY/MM/DD')) ;
INSERT INTO KOKYU_RIREKI(ID, KONYUBI) VALUES(1, TO_DATE('2017/05/07', 'YYYY/MM/DD')) ;
INSERT INTO KOKYU_RIREKI(ID, KONYUBI) VALUES(1, TO_DATE('2016/04/11', 'YYYY/MM/DD')) ;
INSERT INTO KOKYU_RIREKI(ID, KONYUBI) VALUES(2, TO_DATE('2015/06/10', 'YYYY/MM/DD')) ;
INSERT INTO KOKYU_RIREKI(ID, KONYUBI) VALUES(2, TO_DATE('2014/04/09', 'YYYY/MM/DD')) ;
INSERT INTO KOKYU_RIREKI(ID, KONYUBI) VALUES(2, TO_DATE('2013/04/11', 'YYYY/MM/DD')) ;
INSERT INTO KOKYU_RIREKI(ID, KONYUBI) VALUES(3, TO_DATE('2017/05/06', 'YYYY/MM/DD')) ;
INSERT INTO KOKYU_RIREKI(ID, KONYUBI) VALUES(3, TO_DATE('2016/04/07', 'YYYY/MM/DD')) ;
INSERT INTO KOKYU_RIREKI(ID, KONYUBI) VALUES(3, TO_DATE('2014/06/11', 'YYYY/MM/DD')) ;
COMMIT ;
SELECT KR.ID
     , MAX(KR.KONYUBI) AS MAX_KONYUBI
FROM KOKYU_RIREKI KR
WHERE KR.ID IN(2, 3)
GROUP BY KR.ID
ORDER BY KR.ID ;

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/05/08 16:51

    Orlofskyさん。
    大変申し訳ございません。
    そして、ご指摘ありがとうございます。
    追記している間にOrlofskyさんからご回答をいただいてしまいました。
    次回からはしっかりマナーを守り、参加させて頂くように致します。

    キャンセル

  • 2018/05/08 16:55

    今回からマナーを守っても遅くはありません。SQLはデータベースによって方言が大きいのでどのデータベースかタグで明示しましょう。

    キャンセル

  • 2018/05/08 17:26

    ご指摘通り、今回からということで追記させて頂きました。
    それでもわかりづらかったり、見にくかったりしているかもしれません。
    色々な面で皆さんにご迷惑をお掛けしているにも拘らず、
    ご丁寧にご回答を頂いたり、マナーをお教え頂けたりと、
    本当にありがたいことだと改めて思いました。
    今後参加させて頂く際は、今回のようなことがないように気をつけたいと思います。
    ありがとうございました。

    キャンセル

+1

こんなかんじで

  • 元データ
create table tbl(ID int,d date);
insert into tbl values
(1,'2018-04-09'),
(1,'2017-05-07'),
(1,'2016-04-11'),
(2,'2015-06-10'),
(2,'2014-04-09'),
(2,'2013-04-11'),
(3,'2017-05-06'),
(3,'2016-04-07'),
(3,'2014-08-11'); 
  • 検索
select ID,max(d) from tbl as t1
where not exists(
select 1 from tbl as t2
group by ID
having max(d)>'2017-12-31'
and t1.ID=t2.ID
)
group by ID


※結局havingだけでやる方がよさそうですが、上記サブクエリを効率化するとこう

select ID,max(d) from tbl as t1
where not exists(
select 1 from tbl as t2
where d>'2017-12-31'
and t1.ID=t2.ID
)
group by ID

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/05/08 16:56

    あ、たしかにhavingを2段階にする意味はなかったですね
    select ID,max(d) as max_d from tbl
    group by ID
    having max_d<'2017-12-31'

    キャンセル

  • 2018/05/08 17:00

    yambejpさん。
    私の説明が悪く、うまく伝わっていないかもしれません。
    検索のSQL文の「select 1 from tb1 as t2」という部分の「1」はIDの1を指して折るのでしょうか。
    ID=1のデータは結果的に購入履歴の最大値が条件で指定した2017年12月31日よりも後の日付のため取得したくないという意味なのです。
    説明が悪く、申し訳ございません。

    キャンセル

  • 2018/05/08 17:06

    > 「1」はIDの1を指して折るのでしょうか。

    where exists(もしうはwhere not extists)構文はちょっとなれないと分かりづらいですよね
    select 1の「1」はダミーで慣用的につかわれる表現です
    これは1でも0でもnullでもなんでもよく、
    実際にはマッチングしているだけです

    キャンセル

  • 2018/05/08 17:17

    not exists中のgroup byは不要ですね。

    キャンセル

  • 2018/05/08 17:23

    なるほど。
    まだまだ勉強不足でした。
    ご丁寧なご対応、本当にありがとうございました。
    尚、教えて頂きましたSQL文の中で「having max_d<'2017-12-31'」の部分ですが、
    「having max(d)<'2017-12-31'」と記載しないと「max_dは無効です」とエラーが出てしまい、正常に動かなかったのですが、何か私の書き方が不味かったのでしょうか。
    色々と申し訳ございません。

    キャンセル

  • 2018/05/08 17:48

    ああ、すみません
    mysqlではselect句で定義したエイリアスを
    havingで利用できるのでそう書いてました
    SQL Serverでは利用できないのでしょうかね

    キャンセル

  • 2018/05/08 17:54

    TO:saziさん

    ご指摘ありがとうございます。
    existsですからgroup byする意味なかったですね

    キャンセル

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

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

関連した質問

同じタグがついた質問を見る

  • SQL

    2394questions

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