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

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

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

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PDO

PDO(PHP Data Objects)はPHPのデータベース抽象化レイヤーです。

Q&A

解決済

3回答

2769閲覧

MYSQLで複雑な条件で抽出する

SugiuraY

総合スコア317

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PDO

PDO(PHP Data Objects)はPHPのデータベース抽象化レイヤーです。

0グッド

0クリップ

投稿2016/11/01 10:49

編集2016/11/01 11:38

お世話になっております。

下記のようなtable_aがあり、以下のような条件でレコードを抽出したいと考えております。
① Company columnはAに絞る
② Yearが最大のもので絞る。
③ ただし、②のYear最大は少なくとも一つはvalueがNOT NULLが存在する場合の最大のyearとする

この条件の場合id4,id7の2つのカラムが抽出されると思います。
id4 -> company Aであり、Year2016でNOT NULLが存在するため,Yearは2016である。
id6-> company Aであり、Year2016でNOT NULLが存在するため,Yearは2016である。

例えばCompany Bのように2016のレコード自体が存在するが その場合のvalueがすべてNULL(NOT NULLのレコードが存在しない)であるため、Yearは2015が最大として,id8とid12のレコードだけに絞られる。

そこで以下のようなSQL文を考えたのですが、うまく意図した条件で絞ることができません。どなたか、上記の条件で絞ろうとする場合のSQL文をご助言願えますでしょうか。

よろしくお願い申し上げます。

table_a id company name Year value 1 A asset1 2013 100 2 A asset1 2014 150 3 A asset1 2015 200 4 A asset1 2016 220 5 A asset2 2015 100 6 A asset2 2016 NULL 7 A asset3 2016 60 8 B asset4 2015 100 9 B asset4 2016 NULL 10 B asset5 2016 NULL 11 B asset6 2014 30 12 B asset6 2015 25
SQL文 SELECT t1.* from table_a t1 JOIN (SELECT max(year) year from table_a GROUP BY company where value IS NOT NULL) t2 using (year) where t1.company="a"

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

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

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

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

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

KiyoshiMotoki

2016/11/01 11:03

「Company columnはAに絞る 」とき、「id4,id6」だけが抽出されて id7 が抽出の対象から外れるのはなぜですか?
yambejp

2016/11/01 11:22

結果としてidがほしいのでしょうか?yearがほしいのでしょうか?
SugiuraY

2016/11/01 11:39

大変失礼致しました、id4とid7になりますね。修正致しました。
SugiuraY

2016/11/01 11:42

結果として、欲しいのはレコード(1行)です。
hatena19

2016/11/01 12:13

結果が1行で欲しいということですか。 id4, id7 というように。それともidだけでなく該当するレコード全体が欲しいということ?
SugiuraY

2016/11/01 12:20

はい、仰る通りです。
hatena19

2016/11/01 12:27

欲しいのは、A:「結果が1行」なのか B:「該当するレコード全体」なのか、A または B で答えてください。
SugiuraY

2016/11/01 12:33

Bになります。
guest

回答3

0

ベストアンサー

記載されたSQLに対して、コメントを。

SQL

1SELECT t1.* from table_a t1 JOIN (SELECT max(year) year 2from table_a GROUP BY company where value IS NOT NULL) 3t2 using (year) where t1.company="a"


まず、文法が違います。GROUP BY の後にWHERE句は書けません。

SQL

1SELECT t1.* from table_a t1 JOIN (SELECT max(year) year 2from table_a where value IS NOT NULL GROUP BY company) 3t2 using (year) where t1.company="a"

次に、
t1(NULLを含まないtable_aのはずが、table_aのまま)と
t2(company毎のNULLを含まないMAX YEARのはずが、companyがないただの年月リスト)による
紐づけがないので、t1に条件を加え、t2にcompanyを付与し、紐づけします。
(ついでに見やすくします)

SQL

1SELECT t1.* 2from table_a t1 3 INNER JOIN ( SELECT company 4 , max( year ) as year 5 from table_a 6 where value IS NOT NULL 7 GROUP BY company 8 ) t2 ON( 9 t2.company = t1.company 10 AND t2.year = t1.year 11 ) 12where t1.company="a" 13 and t1.value IS NOT NULL

やりたかったのはこの形ですかね。
ちなみに、私なら、以下のSQLです。

SQL

1SELECT t1.* 2from table_a t1 3where t1.company="a" 4 and t1.value IS NOT NULL 5 and t1.year = ( 6 SELECT MAX( t2.year ) 7 FROM table_a t2 8 WHERE t2.company = t1.company 9 and t2.value IS NOT NULL 10 )

投稿2016/11/01 12:57

tomari_perform

総合スコア760

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

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

SugiuraY

2016/11/01 13:09

ご回答ありがとうございます。 t1.value IS NOT NULLについて、少し疑問なのです。 サブクエリでt2.value IS NOT NULLにした上で、where t1.year=t2.yearとしており、どちらもテーブルが同じtable_aである以上、t1.value IS NOT NULLを条件してする意味に理解が及びませんでした。あくまで明示的に示すといったことでしょうか?
hatena19

2016/11/01 13:17

t1.value IS NOT NULL がないと、Yearが最大でvalueがNullのレコード(id=6)も抽出されちゃいますね。
tomari_perform

2016/11/01 14:44

今回の回答は、「valueにNULLがあるデータを抽出しない」場合のSQLになります。 もちろん、抽出結果にNULLが含まれていても構わないのであれば、 「t1.value IS NOT NULL」は不要になります。 (他の回答者が含めていたので、私も流れに乗りました) なお、抽出結果にNULLを含めない事が前提で、少し疑問に思われている場合、 恐らく同一テーブルを参照すれば、t2に条件を付与すると、 t1にも勝手に紐づくものと思われているのかもしれませんが、 異なるFROM句内のテーブルのデータに対して、勝手に紐づく事はありません。 分かりやすく言うと、 全く同じ形のビルが2つあったとしても、FROM句ごとに建っている場所が異なります。 そのため、1つのビルに対して、ある階の電気を消したとしても、 もう1つのビルの電気は付いたままになるんです。 今回のケースでいうと、 t1に対しては、(valueがNULLを含む)company=aのデータを抽出しており、 t2については、(company単位でvalueがNULLを除く)最大yearになります。 t1とt2を紐づける際、 t1.year = t2.year だけでは、 t1.valueがNOT NULLのデータもNULLのデータも抽出されることになるため、 t1.value IS NOT NULL を追加した感じです。
guest

0

companyが"A" で、value が Null でないYearが最大のレコードを抽出

SQL

1SELECT table_a.* 2FROM table_a 3WHERE 4company="A" AND 5value is not null AND 6year = (SELECT Max(Year) 7FROM table_a 8WHERE value Is Not Null AND company="A");

company毎に、value が Null でないYearが最大のレコードを抽出

SQL

1SELECT a.* 2FROM 3table_a AS a INNER JOIN 4(SELECT company, Max(Year) AS maxYear 5 FROM table_a 6 WHERE value Is Not Null 7 GROUP BY company) AS b 8 ON a.company = b.company AND a.year = b.maxYear 9 WHERE a.value Is Not Null;

投稿2016/11/01 11:56

編集2016/11/01 12:24
hatena19

総合スコア33699

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

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

SugiuraY

2016/11/01 13:11

ご回答いただきありがとうございます。 質問をうまくお伝えできなかったにもかかわらず、粘り強く聞いてくださり、ありがとうございます。 ご教示いただいた方法で、実現できました。もっとSQL文を勉強しないとなかなか実践で使用するレベルに至りませんね、、、精進いたします。よろしくお願い申し上げます。
guest

0

SQL

1create table table_a(id int not null primary key,company varchar(20),name varchar(20),year int,value int null); 2insert into table_a values 3(1,'A','asset1', 2013,100), 4(2,'A','asset1',2014,150), 5(3,'A','asset1',2015,200), 6(4,'A','asset1',2016,220), 7(5,'A','asset2',2015,100), 8(6,'A','asset2',2016,NULL), 9(7,'A','asset3',2016,60), 10(8,'B','asset4',2015,100), 11(9,'B','asset4',2016,NULL), 12(10,'B','asset5',2016,NULL), 13(11,'B','asset6',2014,30), 14(12,'B','asset6',2015,25); 15

だとして

SQL

1SELECT t1.company,group_concat(id) as id from table_a as t1 2INNER JOIN ( 3SELECT company,max(year) as year 4from table_a where value IS NOT NULL GROUP BY company 5) as t2 6on t1.year=t2.year and t1.company=t2.company 7group by company; 8

追記

該当するレコードをすべてとりだすならこうしてください

SQL

1SELECT t1.* from table_a as t1 2INNER JOIN ( 3SELECT company,max(year) as year 4from table_a where value IS NOT NULL GROUP BY company 5) as t2 6on t1.year=t2.year and t1.company=t2.company 7WHERE t1.company='A';

投稿2016/11/01 11:47

編集2016/11/01 11:49
yambejp

総合スコア114769

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

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

SugiuraY

2016/11/01 13:02

ご回答をいただき、ありがとうございます。また、言葉たらずの中、諸々汲み取っていただいてしまい、申し訳ございません。 ご教示いただいた方法で実現できました。 yambejp様のお力添え、いつも感謝をしております。 よろしくお願い申し上げます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問