同一テーブル内での商品価格の比較方法

このQ&Aのポイント
  • 商品と商店の区分ごとに、履歴の最も大きい価格を取得します。
  • 商店1を基準に、商品毎に商店2、3の価格差を求めてソートします。
  • 希望の出力は、価格差、商品名、商店の順番です。
回答を見る
  • ベストアンサー

同一テーブル内での比較(最新データによる比較)

大変申し訳ありません。本日も質問させてもらったのですが、一部情報(履歴)が不足していて追加で質問させてください。 以下のようなテーブルがあり、価格が異なるところを差額一覧を出したいと思っております。 (先ほどは2名の方に回答頂き、すみませんベスト10の設定がわからず設定できなくて、すみませんでした。) 【テーブル構成】 商品ID、商店ID、価格(円)、履歴 というテーブルがあり、 商品A、商店1、1000、1 商品A、商店2、1500、1 商品A、商店3、800、1 商品A、商店1、2000、2 商品A、商店2、2500、5 商品A、商店3、1800、3 商品B、商店1、2000、1 商品B、商店2、1700、1 商品B、商店3、2600、1 商品B、商店1、2500、4 商品B、商店2、2000、6 商品B、商店3、2800、7 ・・・(多くの商品データがあります) というデータが格納されております。 商品と商店の区分ごとに履歴の最も大きいものを取り出し (←追加) 商店1を基準に、商品毎に商店2、3の価格差を大きい順にソートして出したいと考えています。 SQL分ではどのように記載すれば良いでしょうか? (実際に比較したデータは以下を抽出し)【履歴の古いのは無視】 商品A、商店1、2000、2 商品A、商店2、2500、5 商品A、商店3、1800、3 商品B、商店1、2500、4 商品B、商店2、2000、6 商品B、商店3、2800、7 ・・・(多くの商品データがあります) (今回の場合の希望出力が以下のような感じです。) 価格差、商品名、商店 (←綱目です。) 800、商品B、商店3 500、商品A、商店2 -200、商品A、商店3 -500、商品B、商店2 ご教授頂けると幸いです。 ちなみに、教えて頂いたSQLをもとに以下のようにやってみましたが、うまくいきませんでした。。。 全くよくわかっていません。少し解説を入れて頂けると幸いです。 ------------------------------------ SELECT a.価格 - b.価格 AS 価格差, a.商品ID AS 商品名, a.商店ID AS 商店 FROM 対象テーブル a INNER JOIN 対象テーブル b ON (a.商品ID = b.商品ID AND b.商店ID = '商店1') WHERE a.商店ID <> '商店1' AND a.履歴 = (SELECT MAX(a.履歴)) AND b.履歴 = (SELECT MAX(b.履歴)) 【←追加】 ORDER BY a.価格 - b.価格 DESC; ---------------------------------------- select t2.価格-t1.価格 as 価格差 ,t1.商品名 ,t1.商店 from テーブル1 as t1 left join ( select 価格,商品 from テーブル1 where 商店=商店1 ) as t2 on t1.商品 = t2.商品 where t1.商店<>商店1 AND a.履歴 = (SELECT MAX(a.履歴)) AND b.履歴 = (SELECT MAX(b.履歴)) 【←追加】 ORDER BY t2.価格 - t1.価格 DESC;

  • MySQL
  • 回答数3
  • ありがとう数12

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

  • ベストアンサー
  • root139
  • ベストアンサー率60% (488/809)
回答No.3

商品B-商店3の価格差は 2800 - 2500 なので300になる気がしますが・・・。 それで良いのなら、下記の様なSQLでよろしいかと。 ---------------------------------------- SELECT a.価格 - b.価格 AS 価格差, a.商品ID AS 商品名, a.商店ID AS 商店 FROM 対象テーブル a INNER JOIN 対象テーブル b ON (a.商品ID = b.商品ID AND b.商店ID = '商店1') WHERE a.商店ID <> '商店1' AND a.履歴 = (SELECT MAX(履歴) FROM 対象テーブル c WHERE a.商店ID = c.商店ID AND a.商品ID = c.商品ID) AND b.履歴 = (SELECT MAX(履歴) FROM 対象テーブル d WHERE b.商店ID = d.商店ID AND b.商品ID = d.商品ID) ORDER BY a.価格 - b.価格 DESC; ---------------------------------------- a, b, に対して、それぞれ、商店IDと商品IDが同じものの中で履歴が最大の行だけを抽出しています。 同じ事は EXISTS 句を使っても表現できます。 ---------------------------------------- SELECT a.価格 - b.価格 AS 価格差, a.商品ID AS 商品名, a.商店ID AS 商店 FROM 対象テーブル a INNER JOIN 対象テーブル b ON (a.商品ID = b.商品ID AND b.商店ID = '商店1') WHERE a.商店ID <> '商店1' AND NOT EXISTS (SELECT * FROM 対象テーブル c WHERE a.商店ID = c.商店ID AND a.商品ID = c.商品ID AND a.履歴 < c.履歴) AND NOT EXISTS (SELECT * FROM 対象テーブル d WHERE b.商店ID = d.商店ID AND b.商品ID = d.商品ID AND b.履歴 < d.履歴) ORDER BY a.価格 - b.価格 DESC; ---------------------------------------- こっちは a, b, に対して、それぞれ、商店IDと商品IDが同じでそれより履歴が大きな行が存在しないものだけを抽出しています。 結果として、商店IDと商品IDが同じものの中で履歴が最大の行を取出す事になり、前のSQLと同じ意味になります。 また、サブクエリーで絞り込んでしまい、それを INNER JOIN する方法も有りますね。 ---------------------------------------- SELECT a.価格 - b.価格 AS 価格差, a.商品ID AS 商品名, a.商店ID AS 商店 FROM ( SELECT * FROM 対象テーブル c WHERE 商店ID <> '商店1' AND NOT EXISTS (SELECT * FROM 対象テーブル d WHERE c.商店ID = d.商店ID AND c.商品ID = d.商品ID AND c.履歴 < d.履歴) ) a INNER JOIN ( SELECT * FROM 対象テーブル e WHERE 商店ID = '商店1' AND NOT EXISTS (SELECT * FROM 対象テーブル f WHERE e.商店ID = f.商店ID AND e.商品ID = f.商品ID AND e.履歴 < f.履歴) ) b USING (商品ID) ORDER BY a.価格 - b.価格 DESC; ---------------------------------------- http://gihyo.jp/dev/serial/01/sql_academy2/000901 http://gihyo.jp/dev/serial/01/sql_academy2/000902 http://codezine.jp/article/detail/907

yamakiyo2
質問者

お礼

素晴らしいです。 助かりました。これで出力できました。 こういう風にかけば良いんですね。あまりわかってないので 応用が聞きそうにありませんが、理解していきます。 ありがとうございました。

その他の回答 (2)

回答No.2

create temporary table temp select t1.商品ID ,t1.商店ID ,t1.価格 from テーブル1 as t1 inner join ( select 商品ID,商店ID,max(履歴) as 履歴 from テーブル1 group by 商品ID,商店ID ) as t2 on t1.商品ID = t2.商品ID and t1.商店ID = t2.商店ID and t1.履歴=t2.履歴; ここでセミコロンですね。

yamakiyo2
質問者

お礼

ありがとうございます。 やはり、ここでセミコロンですね。 ただ、後のSELECT文でtempをテーブルではopenできないというエラーが発生します。。。 他に方法があれば教えて頂ければ、お願いします。

yamakiyo2
質問者

補足

tempで開けない理由がわかりました。 ------------ create temporary table temp select t1.商品ID ,t1.商店ID ,t1.価格 from テーブル1 as t1 inner join ( select 商品ID,商店ID,max(履歴) as 履歴 from テーブル1 group by 商品ID,商店ID ) as t2 on t1.商品ID = t2.商品ID and t1.商店ID = t2.商店ID and t1.履歴=t2.履歴; SELECT * FROM temp; -------------------- は実行できました。JOINの中でtempを使うとcann't openとなるようです。 何かわかれば教えてもらえれると助かります。 よろしくお願いします。

回答No.1

一回履歴で絞り込んだ結果をテンポラリテーブルに入れるのが良いと思います。 create temporary table temp select t1.商品ID ,t1.商店ID ,t1.価格 from テーブル1 as t1 inner join ( select 商品ID,商店ID,max(履歴) as 履歴 from テーブル1 group by 商品ID,商店ID ) as t2 on t1.商品ID = t2.商品ID and t1.商店ID = t2.商店ID and t1.履歴=t2.履歴 select t2.価格-t1.価格 as 価格差 ,t1.商品名 ,t1.商店 from temp as t1 left join ( select 価格,商品 from temp where 商店=商店1 ) as t2 on t1.商品 = t2.商品 where t1.商店<>商店1 ORDER BY t2.価格 - t1.価格 DESC; t1テーブルは基準となるテーブルです。 そこに価格,商品毎にmaxの履歴を絞り込んだt2テーブルを内部結合することによって古い履歴は排除されます。 その結果をテンポラリテーブルに突っ込みます。 ※すみません、mysqlでテンポラリテーブル使ったことないのでこれでいけるでしょうといったところですが。 あとは前回回答したとおりのことをテンポラリテーブルからおこなっているだけです。 やってることは商店1で絞り込んだ結果をサブクエリで結合しているだけです。 説明下手で申し訳ないですがわかりますでしょうか。

参考URL:
http://logic.moo.jp/data/archives/11.html
yamakiyo2
質問者

お礼

ありがとうございます。鋭意努力中です。 こんなことができるんですね。勉強させて頂きます。 ちなみに、create temporary table tempではエラーが出ないのですが、 このSQL文は;(セミコロン)は最後にのみ付与すれば良いのでしょうか? 構文を見直していますが、 select t2.価格-t1.価格 as 価格差 ,t1.商品名 ,t1.商店 phpMyadminで実行してみていますが、上記の文のところでエラーが発生します。 よろしくお願いします。

関連するQ&A

  • 同一テーブル内での比較(2つの条件での比較)

    大変申し訳ありません。ほかにも似たようなのがあるのですが、応用が利かずわかりませんので、ご教授頂けると幸いです。 以下のようなテーブルがあり、価格が異なるところを差額一覧を出したいと思っております。 【テーブル構成】 商品ID、商店ID、価格(円) というテーブルがあり、 商品A、商店1、1000 商品A、商店2、1500 商品A、商店3、800 商品B、商店1、2000 商品B、商店2、1700 商品B、商店3、2600 ・・・(多くの商品データがあります) というデータが格納されております。 商店1を基準に、商品毎に商店2、3の価格差を大きい順にソートして出したいと考えています。 SQL分ではどのように記載すれば良いでしょうか? (今回の場合の希望出力が以下のような感じです。) 価格差、商品名、商店 (←これは当然、出力されない) 600、商品B、商店3 500、商品A、商店2 -200、商品A、商店3 -300、商品B、商店2 ご教授頂けると幸いです。

    • ベストアンサー
    • MySQL
  • データの無いテーブルと結合してデータ抽出

    以下のテーブルを使用してデータを抽出したいのですが、データが抽出できません。 名称テーブル -------------------- ID | NAME | -------------------- 0   AA 1   BB 2   EE 3   FF 履歴テーブル -------------------- ID | DAY | OLDNAME -------------------- 2   2004   CC 3   2004   DD 結果取得したいデータ -------------------- ID | NAME | OLDNAME -------------------- 0   AA =現在のSQL= SELECT A.ID, A.NAME, B.OLDNAME FROM 名称 A , 履歴 B WHERE A.ID = B.ID(+) AND A.ID=0 AND B.DAY =  (SELECT MAX(C.DAY)  FROM 履歴 C  WHERE  A.ID = C.ID(+)) 履歴テーブルには名称テーブルの履歴があります。 履歴にデータが無くても名称データを取得したいのですが、こういった場合はどのようなSQLを作ればいいのでしょうか。

  • フォームから2つのテーブルにデータを書き込みたい

    Accessで T_aテーブルとT_bテーブルがありそれぞれのフィールドが以下のようになっているとします。 T_a:フィールド名 データ型    ID  オートナンバー型    商品番号 テキスト型 主キー T_b:フィールド名 データ型    ID  オートナンバー型 主キー    商品番号 テキスト型 このときフォームから入力したデータをそれぞれのテーブルの商品番号に追加したいのですがどのようにすればよいのでしょうか。  よろしくお願いいたします。

  • 別テーブルのデータ結合

    PostgresSQLを勉強中です。 そこで質問ですが、A、Bという各テーブルの値の合計を求めたいのですがいまいちわからないので教えてください。 例 Aテーブル: ID type 値段 date 0001 あ 100 0902 0002 あ 110 0903 0003 え 421 0910 Bテーブル: ID type 値段  date 0001 お 500 0901 0002 か 210 0801 0004 さ 333 0901 となっているときにA,Bテーブルの合計をtypeは関係なく出したいのです。 たとえばIDが0001であれば100+500で600というかんじです。 下記のように結合はできましたが値段部分の総合計をどうやってだせばいいのかわかりません。 select date,type,値段 from Aテーブル where ID = '0001' and date >= '0901' UNION select date,type,値段 from Bテーブル where ID = '0001' and date >= '0901' order by date 簡単なのかもしれませんがおしえてください。 よろしくお願いします。

  • 複数行の結果を単一列に連結(複数のテーブルを参照)

    psql (PostgreSQL) 7.3.4です。 困っています 以下のような【TABLE1】と【TABLE2】を TABLE1のt1tot2にで結合した結果を 【A.結果】のように★▲●の行を1行に表示させて取得したいのですがうまくいきません。 【TABLE1】 ID,ID_SUB, TYPE, VALUE A A1 t1 1 ★ A A1 t2 2 ★ A A1 t1 1 ▲ A A1 t2 3 ▲ B B1 t1 1 ● B B1 t2 3 ● 【TABLE2】 ID, TYPEV1 ,TYPEV2 ,Code A 1 1 AAA1 A 1 2 AAA2 ★ A 1 3 AAA3 ▲ B 1 3 BBB1 ●  TYPEV1=TABLE1のt1の値 TYPEV2=TABLE1のt2の値 【得たい結果】 ID, ID_SUB, TYPEV1, TYPEV2,Code A A1 1 2 AAA2★ A A1 1 3 AAA2▲ B B1 1 3 BBB1● 下記でTABLE1の2行を1行にまとめることができましたが、 問題のTABLE2との連結方法が分かりません。 select TABLE1.ID , TABLE1.ID_SUB , TABLE1.VALUE as t1 , (SELECT tbl1.VALUE FROM TABLE1 tbl1 where tbl1.TYPE=t2 and (TABLE1.ID , TABLE1.ID_SUB)=(tbl1.ID , tbl1.ID_SUB)) as t2 from TABLE1 where TABLE1.TYPE = t1 【結果】 ID ,ID_SUB , t1  ,t2 A A1 1 2 ★ A A1 1 3 ▲ B B1 1 3 ● 何か良い方法はありますでしょうか?

  • access 2つのテーブルの最新日付の大小

    顧客はIDにて管理していて、請求日テーブルに顧客ID、請求日の2つのフィールド、入金日テーブルに顧客ID、入金日と作り、どんどん追加していく仕組みにしています。 ここで、未入金の顧客を探したいと思っています。 入金日>請求日であれば出るとは思うのですが、SQLにて select max(T入金日.入金日) as 入金日, T入金日.ID from T入金日 group by T入金日.ID と作り、同様に請求日の式も作りましたが、この式どうしを比べる方法がわかりません。 クエリのデザインビューでも同じようなところまでは作れるのですが… また、請求日を基準にして前後半年入金のない顧客を探せる方法もあれば合わせて教えていただきたいです。 ヒントや作り方でもいいので、何かご教授ください

  • 同一テーブルの同一フィールドで複数条件 and 指定

    http://oshiete1.goo.ne.jp/kotaeru.php3?q=1069795 で質問した続きです。 うっかり詳細のテストをしてないのに締め切ってしまいました。 テーブルA 「member」 | id | name | テーブルB 「item」 | id | name | テーブルC 「item_check」 | member_id | item_id | というテーブルがあります。 テーブルAはメンバーで一人一つのデータが入っています。 テーブルBはメンバーが持つであろうアイテムのマスタです。 テーブルCはメンバーがどのアイテムを持っているかを示しているテーブルです。 テーブルCに関しては同じメンバーでも複数のアイテムを持つこともあるので複数のデータが入る場合もあります。 で、やろうとしているのは、 「アイテムA と アイテムBを持っているメンバー」 という検索を行いたいのです。 select distinct a.id, a.name from member as a,item as b,item_check as c where a.id = c.member_id and c.item_id = b.id and (c.item_id = '2' or c.item_id = '3') select member.*,item.name from member, item, item_check where member.id=item_check.member_id and item.id=item_check.item_id and item.id in (1, 3) group by member.id で or 検索はできますが、 and 検索をすると 「Empty set」となってしまいます。 select distinct a.id, a.name from member as a,item as b,item_check as c where a.id = c.member_id and c.item_id = b.id and (c.item_id = '2' and c.item_id = '3') なにかいい手はないでしょうか。

    • ベストアンサー
    • MySQL
  • oracle 最新日付との比較

    いま、同一商品番号の最新日付を利用した条件が うまく作れず悩みながら色々試していますが、 うまくいきません。 やりたいことは、 1,AテーブルとBテーブルの 商品番号が同じ場合は除外します。 2,残されたデータから次はCテーブルの中にある 同一商品番号で、最新の日付が当月の場合はデータを残す。 つまり、前月以前のデータは除外となります。 1まではできています。 Select * from aテーブル where not exists (select 'X' from bテーブル where a.商品番号 = b.商品番号) この先上記sqlにつなげてmax関数くくった最新日付と システム日付を年月のみで比較する等試みましたが、 求めた結果になりません。 上記sqlでビューを作成してといったことは、 今回やらずに一つのsqlのみでできないかと 試行錯誤です。 よきアドバイスございましたら、 宜しくお願い致します。

  • 複数のテーブルからのデータ抽出

    こんばんは。お世話になっております。 テーブル(A) id | no | image -------------------- 1 | みかん| aaa.gif 2 | なし | bbb.gif 3 | いちご| ccc.gif テーブル(B) m_id | t_id ---------------- 1  |  3 2  |  2 1  |  2 というようなテーブルがあるのですが、テーブルBのm_id、1を検索した際、t_idを抽出、かつそのt_idと同じ番号であるテーブルAのimageをも抽出したいと考えています。 結果としては、以下のような感じ。 3  ccc.gif 2  bbb.gif $m_id =$_GET["id"]; //途中省略 $sql= "select * FROM B INNER JOIN A ON B.m_id = A.id WHERE m_id = '$m_id'"; としているのですが、テーブルBのt_idは検索されるものの、テーブルAのimageは全てaaa.gifと返ってきてしまいます。 先日、こちらでテーブルの正規化として、データを分散させる考え方をお教え頂き、早速それに習って構成してみたのですが、思うようにデータを抽出出来ずにアドバイスを頂戴したく投函させていただきました。 先のソースで可笑しな点などの忠告や、アドバイスなど頂戴できれば幸いです。宜しくお願い致します。

    • ベストアンサー
    • MySQL
  • ACCESSで指定されたテーブルから削除できませんでしたとエラー

    お世話になります。 似たような問題をググッてみたのですが、イマイチ解決に繋がらず、 最終手段と質問させて頂きました。 現在、ACCESS2007で削除クエリを作成していますが、 題名のエラーが表示されてしまいます。 ・テーブルAとBが存在します。 ・テーブルBのレコードを削除したいです。 ・削除条件は、テーブルAでSELECTした結果に対し、  テーブルAとテーブルBで一致するものを削除します。 ・A/B両テーブルともに主キーは設定されていません。 ・また、リレーションも張っていません。 ・データシートビューは想定したものが表示されます ・作成したSQLは以下のような感じです。 --------------------------------------------------- DELETE T2.* FROM T2, ( SELECT * FROM T1 WHERE T1.Fld1 = "01" AND T1.Fld2 = "002" AND T1.Fld3 BETWEEN #2008/4/1# AND #2009/3/31# AND (T1.Fld4 ="A" OR T1.Fld5 = "B") ) AS T1a WHERE T2.Fld1 = T1a.Fld1 AND T2.Fld2 = T1a.Fld2 AND T2.Fld3 = T1a.Fld3 --------------------------------------------------- 以上、解決策を伝授頂けないでしょうか? よろしくお願いします。