2012-04-25 7 views
4

私は3つのテーブルを持っています。フィールドPRICEの違いを3つの異なるテーブルを使用して確認し、上位3つの最も大きなマイナスの差異を表示するよい方法を探してください。私はまず、使用する最良のMySQLクエリを見つけて、それをPHPですべて表示する最良の方法を見つけたいと思います。UNION SELECT MySQLのクエリは、PHPで数学と表示を行う

MAINTABLE:

COMPANY  | MODEL | PRICE 
Main Company | ProductA | 100.00 
Main Company | ProductB | 50.00 
Main Company | ProductC | 25.00 
Main Company | ProductD | 300.00 

COMPTABLE1:

COMPANY  | MODEL | PRICE 
Competitor1 | ProductA | 100.00 //0 
Competitor1 | ProductB | 55.00 //5 
Competitor1 | ProductC | 50.00 //25 
Competitor1 | ProductD | 200.00 //-100 

COMPTABLE2:

COMPANY  | MODEL | PRICE 
Competitor2 | ProductA | 99.00 //-1 
Competitor2 | ProductB | 44.00 //-6 
Competitor2 | ProductC | 20.00 //-5 
Competitor2 | ProductD | 100.00 //-200 

だから私のページに表示された私が欲しい価格で最大の負の違いは次のとおりです。

  1. Competitor2 ProductDメイン・カンパニーProductDから-200違い
  2. Competitor1 ProductD -100違いメインから会社ProductD
  3. Competitor2 ProductB -6主な会社ProductB

IDEAとの違い:私はそれほど親密ではありませんが、私はUNION SELECTを3つのテーブルに使用することができますWHERE MODEL=XXX。データを収集し、数学を行い、情報を吐き出して、それぞれをループする可能性があります。問題は、各変数を各テーブルの独自の価格として保存する方法がわからないことです。また、数学の後に各変数を保存し、次に上位3つの違いを表示する方法がない限り、すべての違いを表示すると思います。

このクエリに最適なアイデアや提案があれば幸いです。 (注:1つのテーブルにすべてを入れることはできません)

答えて

5

PHP側では助けになることはできませんが、このクエリでは必要なものを得ることができます。すべての認定結果を取得するには、組合をする必要があります。これにより、使用可能なすべての列が事前計算され、必要な方法で簡単なグリッドリストに入れることができます。計算は競合他社との主な会社であるため、価格差は自然順序を基準にすると負のものが最も大きく、次に正のものになります。したがって、注文後にLIMITコマンドが適用され、3つのレコードが返送されます。

select 
     MT.Model, 
     MT.Company as MainCompany, 
     MT.Price as MainPrice, 
     CT1.Company as Competitor, 
     CT1.Price as CompPrice, 
     CT1.Price - MT.Price as PriceDifference 
    from 
     MainTable MT 
     JOIN CompTable1 CT1 
      on MT.Model = CT1.Model 
UNION 
select 
     MT.Model, 
     MT.Company as MainCompany, 
     MT.Price as MainPrice, 
     CT2.Company as Competitor, 
     CT2.Price as CompPrice, 
     CT2.Price - MT.Price as PriceDifference 
    from 
     MainTable MT 
     JOIN CompTable2 CT2 
      on MT.Model = CT2.Model 
order by 
    PriceDifference 
limit 3 

提案...あなたのテーブルが構造化されている方法は、長距離のために本当に悪いです。パフォーマンスを最適化するには、データを正規化する必要があります。競争相手が100人いるとどうなりますか?あなたはどこにでも複製を持っています。モデル名も変更してください。ここでは、別のベンダーの価格設定を取得したい場合は、適切なインデックスと、その後...私はテーブルを再構築する方法をない、明示的なデータ型が、概念的に

COMPANY 
    CompanyID  auto-increment 
    CompanyName character 

PRODUCT 
    ProductID  auto-increment 
    ProductModel character 

VendorPricing 
    VPriceID  auto-increment 
    CompanyID  (ID pointing to company table -- to get name when needed) 
    ProductID  (ID pointing to product table -- to get model name too) 
    Price   actual price for this particular company and product 

で、どんなモデル、クエリ将来的には拡大が容易になるだろう...

select 
     VP1.CompanyID, 
     C1.CompanyName as MainCompany, 
     C2.CompanyName as Competitor, 
     P1.ProductModel, 
     VP1.Price as MainPrice, 
     VP2.Price as CompetitorPrice, 
     VP2.Price - VP1.Price as PriceDifference 
    from 
     VendorPricing VP1 

     JOIN Company C1 
      on VP1.CompanyID = C1.CompanyID 

     JOIN Product P1 
      on VP1.ProductID = P1.ProductID 

     JOIN VendorPricing VP2 
      on VP1.ProductID = VP2.ProductID 
      AND NOT VP1.CompanyID = VP2.CompanyID 

      JOIN Company C2 
       on VP2.CompanyID = C2.CompanyID 

    where 
     VP1.CompanyID = TheOneCompanyYouAreInterestedIn 
    order by 
     PriceDifference 
    limit 3 

これで、競合相手が2,5,10,100人の場合、クエリはまったく同じです。

+0

美しい。これまでのところ、私が行ったすべてのテストで動作します。ありがとうございました。 – ToddN

+0

ahem - 下の私のソリューションは、より柔軟で効率的です。 – mson

+1

@ToddN、これはすべての製品に共通ですが、特定の単一モデルの競合他社のリストが必要な場合は、WHERE句として追加します各ユニオン...または、あなたがモデルごとにトップ3を望むなら、それも異なったクエリでしょう。 – DRapp

0

mysqlで重い計算をするのは悪い考えです。私たちのプロジェクトでは、私たちのゲームの一部をmysqlに最適化するのに非常に苦労しています。そして、最善の決定は、phpコードで厳しい数学を計算してからmysqlで行うことでした。だからあなたのところで私はPHPでそれをコード化し、単純なクエリといくつかの結合のためだけにMySQLを使用したいと思います。

1
SELECT CASE WHEN C1.Price<C2.Price THEN C1.COMPANY ELSE C2.COMPANY END AS company, 
     M.Model, 
     CASE WHEN C1.Price<C2.Price THEN C1.Price-M.Price ELSE C2.Price-M.Price END AS diff 
FROM MAINTABLE M, COMPTABLE1 C1, COMPTABLE2 C2 
WHERE M.Model=C1.Model AND M.Model=C2.Model 
ORDER BY diff ASC 
LIMIT 3 
1
select mt1.company, tt1.company, mt1.price, tt1.price, (mt1.price - tt1.price) as delta 
from mt1 
    -- treats tables as single table and allows you flexibility to add more later 
    left join (
    select company, model, price from t1 
    union 
    select company, model, price from t2 
    ) tt1 on tt1.model = mt1.model 
order by (mt1.price - tt1.price) 
limit 3 -- actually should be parameter to sproc 

あなたはヌルと欠損値を考える必要があります。あなたは何も指定しなかったので、私はそれらを扱っていませんでした。

誰かが以前に計算を行っているmysqlで悪いパフォーマンスを言いました。このようなことはまさにデータベースが設計されたものです。パフォーマンスが悪いのは、それが「スマート」ではなく、自動的にSQL Server、Postgres、oracleなどの最適化されたプランを作成することです。ここで最適化するためにできることの1つは、価格列が数値であり、モデル列が各表で索引付けされていることを確認することです。

オフトピック - しかし、あなたがmysqlを使ってgoogleについて聞いたとき - 彼らはシステムを最適化するdbaの達人のチームを持っています。 SQL Server express(free)またはpostgres(open source)を使用すると、小規模店舗の方がおそらく良いでしょう。

+0

はい、企業、モデル、価格を組み合わせるという内部的なクエリは効率的に見えますが、派生/ユニオンテーブルのインデックスを利用しないでパフォーマンスが低下する可能性があります。特定の状況下では、私もあなたがここにあるように、完全なテーブルを防ぐための既知の基準が完全なテーブルに加わったときにのみ、連合のルートを行くでしょう。確かに意見の違いはありますが、どちらもうまくいくと思います。 – DRapp

+0

良い点drapp。派生テーブルがパフォーマンス上の問題になった場合、私はインデックス付きビューを作成します。実際には、2つの顧客テーブルが適切に設計されておらず、とにかく1つのテーブルになるはずです。 – mson

関連する問題