こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

一番新しいdatetime型列があるレコードを取得

下記条件を満たすSQL文を知りたいのですが、どう書けばよいでしょうか?

■構成
Aテーブル
・「id」カラム
・「created_at」カラム … datetime型
・「area」カラム

Bテーブル
・「a_id」カラム
・「created_at」カラム … datetime型

■前提
・Aテーブルの1レコード(「id」カラム)に対して、0~複数のBテーブルレコード(「a_idカラム」)がある
・A.id = B.a_id


■欲しい内容
・「Aテーブル」「Bテーブル」それぞれのカラム内容全部。※条件あり

▼条件1
Aテーブル「id」カラムに対応したBテーブルの「a_id」が複数ある場合には、該当Aテーブル内容+
Bテーブル「created_at」カラムの値が一番新しいレコードを返す(取得レコード数は常に1)

▼条件2
Aテーブル「id」カラムに対応したBテーブルの「a_id」がなかった場合には、該当Aテーブル内容+
Bテーブル側は何も返さない

▼条件3
※同名カラムを取得する際には、カラム名先頭にそれぞれa、bを付与(「acreated_at」「bcreated_at」)
・後で、それぞれのテーブルカラムとして利用したいだけなので、それが出来れば形式にこだわりはありません

投稿日時 - 2012-12-04 19:42:15

QNo.7829808

暇なときに回答ください

質問者が選んだベストアンサー

ANo1です。

<追加したい条件4>
・Bテーブル「created_at」カラムの値で、一番新しいレコードが複数あった場合、
Aテーブル「id」カラム(int型)が一番大きいレコードを1件返す

ですけど、

■前提
・Aテーブルの1レコード(「id」カラム)に対して、0~複数のBテーブルレコード(「a_idカラム」)がある
・A.id = B.a_id

からいうと、
一番新しいレコードが複数あった場合、
Aテーブル「id」カラム(int型)は同じ値になるはずですけど。

★ひとつだけ2件重複取得されているレコードがありました。
というのが、まったく同じレコードが2件出てきたということなら、

当初の回答のselectの次にdistinctをいれればよい。

select distinct a.id,a.created_at as Acreated_at,a.area,
b.a_id,b.created_at as Bcreated_at
from Atable a left outer join Btable b
on a.id = b.a_id
and b.created_at
= (select max(c.created_at) fron Btable c
where c.a_id = b.a_id)

★この質問に挙げた仕様はサンプルレベルなので、実際には、Bテーブルのほかの項目もselectしている
ならば、Bテーブルのほかの項目で判断しないと意味がないと思われます。
・・・該当するほかの項目を挙げてもらえばSQLを直します。

投稿日時 - 2012-12-06 22:34:24

お礼

回答ありがとうございました。
大変参考になりましたー

投稿日時 - 2013-05-09 08:53:47

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

-広告-
-広告-

回答(4)

ANo.3

ごめんなさい。データベース久々に触ったので・・・

GROUP BY すると、ORDER BY 関係なくなるみたいです。

SELECT
id
,t1.created_at AS acreated_at
,area
,t2.created_at AS bcreated_at
FROM
A AS t1
LEFT OUTER JOIN( # B が存在しないA テーブルの値がいらない場合は RIGHT OUTER JOIN で
SELECT
a_id
, MAX(created_at) AS created_at
FROM
B
GROUP BY a_id
) AS t2 ON t1.id = t2.a_id

投稿日時 - 2012-12-05 11:29:59

お礼

回答ありがとうございました。
大変参考になりましたー

投稿日時 - 2013-05-09 08:54:16

ANo.2

SELECT
id
,t1.created_at AS acreated_at
,area
,t2.created_at AS bcreated_at
FROM
A AS t1
LEFT OUTER JOIN(
SELECT
a_id
, created_at
FROM
B
ORDER BY created_at DESC
GROUP BY a_id
) AS t2 ON t1.id = t2.a_id

でいけると思う。確認してないからちょっと自信なし

投稿日時 - 2012-12-04 21:46:18

補足

回答ありがとうございました。

試してみたのですが、

ORDER BY created_at DESC
GROUP BY a_id

の順番だと、自分の環境ではsyntaxエラーになるので、

GROUP BY a_id
ORDER BY created_at DESC

としたみたのですが、
そうすると、取得結果が昇順(?)になります。

「GROUP BY」使ったことがないので、どうすれば良いかもうひとつよく分からないのですが、
何かアドバイス等あればよろしくお願いします

投稿日時 - 2012-12-05 02:13:39

ANo.1

select a.id,a.created_at as Acreated_at,a.area,
b.a_id,b.created_at as Bcreated_at
from Atable a left outer join Btable b
on a.id = b.a_id
where b.created_at
= (select max(c.created_at) fron Btable c
where c.a_id = b.a_id)

別にwhereでなくてandでもいいけれど。

投稿日時 - 2012-12-04 21:45:41

補足

回答ありがとうございました。
おかげで希望通り動作させることが出来ました!

出来たのですが、当初想定していなケースがあったので、再度教えていただくことは可能でしょうか?

<追加したい条件4>
・Bテーブル「created_at」カラムの値で、一番新しいレコードが複数あった場合、
Aテーブル「id」カラム(int型)が一番大きいレコードを1件返す

<補足背景>
・SQL文(and利用)で取得したデータが欲しかったデータなのですが、ひとつだけ2件重複取得されているレコードがありました。確認したところ、Bテーブル「created_at」カラムに同じ値が2件あり、それがたまたま一番新しい日付だったため、発生したようでした。質問した時点ではそこまで頭が回らなかったのですが、select maxで対象が2件以上あったとき、さらに別の条件を追加するにはどうすればよいでしょうか?

投稿日時 - 2012-12-05 01:04:45

-広告-
-広告-

あなたにオススメの質問

-広告-
-広告-