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

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

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

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

Q&A

解決済

3回答

8220閲覧

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

matsutake

総合スコア34

SQL

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

0グッド

0クリップ

投稿2018/05/08 07:24

編集2018/05/08 08:15

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文は以下になります。

SQL

1CREATE TABLE [購入履歴] ( 2 [ID] [int] NOT NULL PRIMARY KEY, 3 [BuyDate] [varchar(14)] [NOT NULL] 4 );

SQL

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

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

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

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

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

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

m.ts10806

2018/05/08 07:25

ご自身で書かれたSQLを提示してください。
m.ts10806

2018/05/08 07:26

また、テーブル定義をご提示ください。それぞれのカラムの型によってやり方が決まってきます。
sazi

2018/05/08 07:39

DBMSは何ですか?分析関数に対応しているDBMSだと効率が良さそうです。
sazi

2018/05/08 07:41

「ID=1は取得したくない」とありますが、条件は「ID=1を除く」ですか?
matsutake

2018/05/08 08:08

saziさん。わかりにくい説明で申し訳ございません。結果的に今回の場合ですと、IDが1のデータは取得しないという意味で記載させて頂いたつもりでした。
sazi

2018/05/08 08:12 編集

「購入日が2017年12月31日以降のデータを含む、IDを除く」ということでしょうか?また、DBMSをタグなりで明確にして下さい。
matsutake

2018/05/08 08:16

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

2018/05/08 08:19

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

2018/05/08 08:27

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

回答3

0

ベストアンサー

こんなかな?

SQL

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

投稿2018/05/08 07:46

hihijiji

総合スコア4150

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

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

matsutake

2018/05/08 08:32

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

0

こんなかんじで

  • 元データ

SQL

1create table tbl(ID int,d date); 2insert into tbl values 3(1,'2018-04-09'), 4(1,'2017-05-07'), 5(1,'2016-04-11'), 6(2,'2015-06-10'), 7(2,'2014-04-09'), 8(2,'2013-04-11'), 9(3,'2017-05-06'), 10(3,'2016-04-07'), 11(3,'2014-08-11');
  • 検索

SQL

1select ID,max(d) from tbl as t1 2where not exists( 3select 1 from tbl as t2 4group by ID 5having max(d)>'2017-12-31' 6and t1.ID=t2.ID 7) 8group by ID

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

SQL

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

投稿2018/05/08 07:53

編集2018/05/08 08:53
yambejp

総合スコア114839

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

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

yambejp

2018/05/08 07:56

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

2018/05/08 08:00

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

2018/05/08 08:06

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

2018/05/08 08:17

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

2018/05/08 08:23

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

2018/05/08 08:48

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

2018/05/08 08:54

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

0

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

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

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

Oracleですと、

SQL

1CREATE TABLE KOKYU_RIREKI 2 ( 3 ID NUMBER(1) NOT NULL 4 , KONYUBI DATE NOT NULL 5 , CONSTRAINT PK_KOKYU_RIREKI PRIMARY KEY(ID, KONYUBI) USING INDEX 6 ) ; 7INSERT INTO KOKYU_RIREKI(ID, KONYUBI) VALUES(1, TO_DATE('2018/04/09', 'YYYY/MM/DD')) ; 8INSERT INTO KOKYU_RIREKI(ID, KONYUBI) VALUES(1, TO_DATE('2017/05/07', 'YYYY/MM/DD')) ; 9INSERT INTO KOKYU_RIREKI(ID, KONYUBI) VALUES(1, TO_DATE('2016/04/11', 'YYYY/MM/DD')) ; 10INSERT INTO KOKYU_RIREKI(ID, KONYUBI) VALUES(2, TO_DATE('2015/06/10', 'YYYY/MM/DD')) ; 11INSERT INTO KOKYU_RIREKI(ID, KONYUBI) VALUES(2, TO_DATE('2014/04/09', 'YYYY/MM/DD')) ; 12INSERT INTO KOKYU_RIREKI(ID, KONYUBI) VALUES(2, TO_DATE('2013/04/11', 'YYYY/MM/DD')) ; 13INSERT INTO KOKYU_RIREKI(ID, KONYUBI) VALUES(3, TO_DATE('2017/05/06', 'YYYY/MM/DD')) ; 14INSERT INTO KOKYU_RIREKI(ID, KONYUBI) VALUES(3, TO_DATE('2016/04/07', 'YYYY/MM/DD')) ; 15INSERT INTO KOKYU_RIREKI(ID, KONYUBI) VALUES(3, TO_DATE('2014/06/11', 'YYYY/MM/DD')) ; 16COMMIT ;

SQL

1SELECT KR.ID 2 , MAX(KR.KONYUBI) AS MAX_KONYUBI 3FROM KOKYU_RIREKI KR 4WHERE KR.ID IN(2, 3) 5GROUP BY KR.ID 6ORDER BY KR.ID ; 7

投稿2018/05/08 07:46

Orlofsky

総合スコア16415

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

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

matsutake

2018/05/08 07:51

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

2018/05/08 07:55

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

2018/05/08 08:26

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問