お世話になります
大規模商談をまとめた営業のリストを作るSQLを書こうとしています。
営業部員テーブル (test.person)
id | name
----+------
1 | 山田
2 | 高橋
3 | 田中
商談テーブル (test.deal)
id | person_id | customer | amount
----+-----------+----------+--------
1 | 1 | XX商事 | 20000
2 | 3 | BB電機 | 10000
3 | 2 | ZZ不動産 | 2000
4 | 1 | RR証券 | 8000
期待している検索結果
name | amount | customer
------+--------+----------
山田 | 20000 | XX商事
田中 | 10000 | BB電機
高橋 | 2000 | ZZ不動産
下記のようなSQLを書きました。
select distinct name,amount,customer
from test.deal,test.person
where person.id=deal.person_id
order by amount desc
しかし、nameをdistinctしているにもかかわらず、結果は下記の通り、「山田」が重複しています。
name | amount | customer
------+--------+----------
山田 | 20000 | XX商事
田中 | 10000 | BB電機
山田 | 8000 | RR証券
高橋 | 2000 | ZZ不動産
いろいろと調べて、group by を使えばいい、というようなやり方を示している例も多かったのですが、それもうまくいきません。(必要であれば載せます)
期待通りの結果を得るにはどのようなSQLを書けばよろしいでしょうか。
よろしくお願いいたします。
No.5
- 回答日時:
#4回答の1箇所訂正。
<訂正前>
(3)(2)のidと、test_person表を結合する
↓
<訂正後>
(3)(2)のidの行のperson_idと、test_person表を結合する
=====以下、独り言=====
select
person_id,max(amount)
from test_deal
group by person_id
;
select
*
from test_deal as d
where id=(select min(id)
from test_deal
where d.person_id=person_id
having d.amount=max(amount)
)
order by id
;
select
*
from test_person as p
inner join (
select
*
from test_deal as d
where id=(select min(id)
from test_deal
where d.person_id=person_id
having d.amount=max(amount)
)
) as x
on p.id=x.person_id
order by p.id
;
すばらしいです。これは難しいんじゃないかと思っていたので、正直いって驚きました。
実は質問を投稿する前から、これはgroup by で解決できそうに見えて実はそうじゃない、というパターンじゃないかという気がしていました。ですが相関サブクエリなどをちょっと書いてみても、どうもいい方法が思いつかないので質問させていただいた次第です。
group by なしの having というのはまだあまり勉強していないところなので、これを機に調べてみたいと思います。
SQLの奥の深さを改めて教えていただいた気分です。本当にありがとうございました。
No.4ベストアンサー
- 回答日時:
SQLの基本操作の一つである「group by」を、理解できていませんね。
基本操作から、しっかり勉強すべきです。
>実はgroup by も試してみたのですが、どうもうまくいきません。
>とりあえず、下記のようなSQLを書いてみました。
>select name,max(amount),customer
>from test.deal,test.person
>where person.id=deal.person_id
>group by name
>order by max(amount) desc
理解できていないまま、いい加減なことをやっていますよ?
> ERROR: column "deal.customer" must appear in the GROUP BY clause or be >used in an aggregate function;
>言われるままに、group byの中にcustomerを入れると下記のような結果に
>なり、group byを付けても付けなくても同じになります
エラーの内容を取り違えて、デタラメな対処を行っていますよ?
>group by を使用するとして、名前の重複を避けるにはどのようにしたら
名前の重複を起こさない(つまり、どのデータを活かすか?)が、不明瞭だし、SQLとして指定されていないのですよ。
どうしたい(どのデータを活かしたい)のですか?
また、得たい結果(仕様)で、まだまだ不明瞭な点があります。
person_id毎に、最大のamountを得るのは簡単です。
しかし、同じperson_idで求めた最大のamountが、二箇所以上のcustomerで記録されていた場合、どういう結果を得たいのでしょうか?
理解できていないのに、デタラメの上にさらにデタラメを繰り返すのでなく、簡単なクエリから順次、組み立てていきましょう。
今回のクエリは、次の(1)~(3)の順に組み立てていくと、具体的な仕様が明確でない部分が明確になり、SQLの理解も進むと思います。
(1)test_deal表で、person_id毎に最大のamountを得る
(2)(1)に該当するtest_deal表のidを得る
→全idとするのか、最大のidあるいは最小のidとするのか、仕様の明確化が必要
(3)(2)のidと、test_person表を結合する
No.3
- 回答日時:
回答にあるような条件づけをしたいのであれば、Distinctではいけません。
ちゃんとamountがMAXのものだけを収集する条件づけのためにも、Group by句が必要です。
とりあえず、以下のページを参考にしてみてください。
http://www.techscore.com/tech/sql/05_08.html
この回答への補足
ありがとうございます。
実はgroup by も試してみたのですが、どうもうまくいきません。
とりあえず、下記のようなSQLを書いてみました。
select name,max(amount),customer
from test.deal,test.person
where person.id=deal.person_id
group by name
order by max(amount) desc
すると、下記のようなエラーになります。
> ERROR: column "deal.customer" must appear in the GROUP BY clause or be used in an aggregate function;
言われるままに、group byの中にcustomerを入れると下記のような結果になり、group byを付けても付けなくても同じになります
name | max | customer
------+-------+----------
山田 | 20000 | XX商事
田中 | 10000 | BB電機
山田 | 8000 | RR証券
高橋 | 2000 | ZZ不動産
group by を使用するとして、名前の重複を避けるにはどのようにしたらよろしいでしょうか。
よろしくお願いいたします。
No.2
- 回答日時:
何をしたいのかがよくわかりません。
上記の例ですと、山田は2件の商談をまとめたにもかかわらず、どちらか1件(金額が大きい方?)でしか
ランキングに載せたくないわけですか?
「各部員のまとめた商談を、金額の大きい順に並べる。
ただし、複数の商談をまとめた部員は、もっとも金額の大きい商談だけを
表示させる」
という動作?
この回答への補足
はい、そういうことです。
例を変えるならば、こんなものです
1 2.19.41 渋井 陽子 三井住友海上 2004. 9.25 大 阪
2 2.21.47 高橋 尚子 積 水 化 学 1998.12.06 バ ン コ ク
3 2.21.18 野口みずき グローバリー 2003. 1.26 大 阪
4 2.21.45 千葉 真子 豊田自動織機 2003. 1.26 大 阪
5 2.21.51 坂本 直子 天 満 屋 2003. 1.26 大 阪
6 2.22.12 山口 衛里 天 満 屋 1999.11.21 東 京
7 2.22.46 土佐 礼子 三井住友海上 2002. 4.14 ロ ン ド ン
8 2.22.56 弘山 晴美 資 生 堂 2000. 1.30 大 阪
9 2.23.26 大南 博美 UFJ銀行 2004. 9.25 ベ ル リ ン
10 2.23.30 小崎 まり ノ ー リ ツ 2003. 1.26 大 阪
http://www.geocities.jp/majikanahappy/marathonki …
高橋尚子は2時間22分台で何回か走っていますが、ここには載ってません。
No.1
- 回答日時:
>nameをdistinctしているにもかかわらず
重複排除しているのは、nameでだけでなく、name,amount,customerの組み合わせでの指定になっています。
>期待している検索結果
「RR証券」を検索対象から外すのは、どういう条件でですか?
この回答への補足
ありがとうございます。
なるほど、distinctは全てにかかるのですね。とても勉強になりました。
RR証券をはずす条件(というか、理由)は、
この検索結果は営業部員個人のランキングですので、山田さんが1位と3位に2回出てくるのは望ましくない、ということです。
上記、補足になっておりますでしょうか。
よろしくお願いいたします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- MySQL 書籍の内容はまともでしょうか? 1 2023/01/22 03:07
- Oracle sqlで質問です。 aテーブルとbテーブルがあり、下記のsqlで取得したidとnameに一致しないレ 1 2022/04/20 20:34
- Oracle sqlで質問です。 idを元にidに紐付くデータで住所コードがjpのみのデータ以外のidを取得したい 4 2023/03/20 17:41
- MySQL mysqlの結合について教えてください 1 2022/05/19 15:13
- Oracle 質問です。 下記のテーブルとデータがあり、 取得想定結果のように出力したいです。 下記のsqlだと0 2 2023/05/23 19:10
- MySQL 共通点はあります。何が違うのでしょうか? 1 2023/01/27 05:22
- PostgreSQL PostgreSQL レコードからアイテム種類数を取得したい 2 2022/11/23 22:31
- JavaScript Javascript初心者|jQueryの.val()で値を取得し複数の要素を連結させる方法知りたい 2 2022/06/02 12:06
- PHP コメント機能に返信欄を矢印で追加したい 1 2022/05/09 21:17
- その他(プログラミング・Web制作) pythonのWebスクレイピングでfind_allだとurlがNoneに 4 2022/04/17 18:21
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
postgreSQLのint型は桁数指定が...
-
チェックボックスから、データ...
-
テーブルからのselectにおいて...
-
特定カラムの値を変更したいの...
-
列が255以上のCSVファイルをAcc...
-
PL/SQLでテーブル名に変数を使...
-
Viewにインデックスは張れ...
-
SQLでスキーマ名(所有者名)の...
-
【Access】外部結合を行う前に...
-
ORA-00959: 表領域'****'は...
-
ACCESS 複数テーブル・複数フィ...
-
目的のインデックスが使用され...
-
SQL2005 のクエリ文について
-
データ表示順序
-
複数テーブルのUPDATE
-
複数あるAccessのテーブルを一...
-
カラムの存在チェック
-
SQLの速度を調べるには…
-
SQLite C/C++ でのテーブル数...
-
Access2002 マスタテーブル変更...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
postgreSQLのint型は桁数指定が...
-
テーブルからのselectにおいて...
-
クエリアナライザのsp_helpコマ...
-
UNIQUEをつけたときのINDEXテー...
-
PostgressからMySQL(MariaDB)...
-
pl/pgsqlで変数の扱い
-
SQL SELECT文 別テーブルのレコ...
-
SQLで検索結果の記事を表示したい
-
3つのテーブルの処理について
-
PostgreSQLでの複数結果のまとめ方
-
PostgresSQL8.4でツリー上に取...
-
賢いSQL文がわからない
-
SQL文作成のお願い
-
postgreSQLの正規表現
-
テーブル作成 外部参照 配列
-
もうちょっと賢いSELECT文が書...
-
Postgresqlの自己結合について
-
2つの異なるテーブルを和結合し...
-
チェックボックスから、データ...
-
全テーブルのデータの行数
おすすめ情報