2012-04-25 34 views
4

我有3個表。尋找一種使用三個不同表格找到字段PRICE的差異的好方法,然後顯示前三個最大的負面差異。我想先找到最好的MySQL查詢使用,並找到最好的方式來顯示它在PHP中。聯盟選擇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產品B -6從主要產品B公司

IDEA區別:我不是那麼親切,但我可​​以在三張桌子WHERE MODEL=XXX上使用.. UNION SELECT。我可能會循環每一個收集數據,做數學和吐出信息。唯一的問題是,我不知道如何將每個變量存儲爲每個表的自己的價格。另外,我認爲它會顯示所有的差異,除非在數學計算之後存儲每個變量,然後顯示前三個差異。

任何想法或建議,以最好地解決這個問題將不勝感激。 (注意:不,我不能把它們全部放在一張表中= p)

回答

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 2012-04-25 17:14:03

+0

ahem - 我的解決方案下面更靈活,更高效... – mson 2012-04-25 17:27:31

+1

@ToddN,雖然這適用於所有產品,如果你想要一個特定的單一模型的競爭對手名單,我只是將其添加爲WHERE子句每個聯盟......或者,如果你想要每個型號的前3名,那也是一個不同的查詢。 – DRapp 2012-04-25 17:41:20

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在做計算時表現不佳。這類事情正是數據庫設計的目的。從mysql表現不佳更多的不是「聰明」,並自動創建一個優化的計劃,如SQL服務器,Postgres,或甲骨文會。您可以在此處進行優化的一件事是確保價格列是數字,並且模型列是在每個表中建立索引的。

偏離主題 - 但是當你聽說谷歌使用mysql時 - 他們擁有優化其系統的dba gurus團隊。使用sql server express(免費)或postgres(開源)的小型商店可能會更好。

+0

是的,你可能看起來更有效率,但是,你的內部查詢工會公司,模型和價格,但可以得到性能擊中沒有利用派生/聯盟表上的索引。在某些情況下,我也會按照你在這裏的路線走一個聯盟的路線,但只有當一個已知的標準阻止一個完整的表加入一個完整的表。尊重意見分歧,但肯定會起作用。 – DRapp 2012-04-25 17:34:55

+0

好點的drapp。如果派生表成爲性能問題,我會創建一個索引視圖。真的看起來2個客戶桌子的設計不正確,無論如何都應該是單個桌子。 – mson 2012-04-25 17:49:19