4

我有 3 张桌子。寻找一种PRICE使用三个不同表格查找字段差异的好方法,然后显示前 3 个最大的负差异。我想首先找到要使用的最佳 MySQL 查询,并找到在 php.ini 中显示它的最佳方式。

可维护:

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

兼容1:

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

兼容2:

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

因此,我希望在我的页面中显示的 PRICE 的最大负面差异是:

  1. 竞争对手 2 ProductD 与主要公司 ProductD 的差异 -200
  2. 竞争对手 1 ProductD 与主要公司 ProductD 的差异 -100
  3. 竞争对手 2 产品 B -6 与主要公司产品 B 的差异

IDEA:我对它不是很熟悉,但我可以UNION SELECT在三张桌子上使用 .. WHERE MODEL=XXX。我可能会遍历每个收集数据、进行数学运算并吐出信息的人。唯一的问题是,我不知道如何将每个变量存储为每个表的自己的价格。另外,我认为它会显示所有差异,除非有办法在进行数学运算后存储每个变量,然后显示前 3 个差异。

任何可以最好地解决此查询的想法或建议将不胜感激。(注意:不,我不能把它们都放在一张桌子上=p)

4

4 回答 4

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 个竞争对手,那么查询是完全相同的。

于 2012-04-25T17:05:41.120 回答
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
于 2012-04-25T17:10:37.550 回答
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 server、postgres 或 oracle)有关。您可以在此处进行优化的一件事是确保价格列是数字列,并且模型列在每个表中都有索引。

题外话——但是当你听说 google 使用 mysql 时——他们有 dba 专家团队来优化他们的系统。使用 sql server express(免费)或 postgres(开源)可能会更好。

于 2012-04-25T17:23:41.707 回答
0

在 mysql 中进行大量计算是个坏主意。在我们的项目中,我们很难优化游戏中的 mysql 部分。最好的决定是在 php 代码中然后在 mysql 中计算硬数学。因此,在您的位置上,我想在 php 中对其进行编码,并将 mysql 仅用于简单查询和一些连接。

于 2012-04-25T16:58:36.373 回答