通过单个表中的单个列获取三列组的最小值

时间:2013-04-25 09:59:56

标签: mysql

我有一个表,我的表结构是这样的:

unique_id     vendor_name      price1     price2     price3    code 

1             Vendor 1         0.0012     0.0014     0.0054     125
2             Vendor 2         0.0015     0.0016     0.0050     125
3             Vendor 3         0.0011     0.0019     0.0088     125
4             Vendor 1         0.0025     0.0024     0.0034     126
5             Vendor 2         0.0043     0.0019     0.0065     126
6             Vendor 3         0.0019     0.0085     0.0082     126        

我必须按代码获取每个价格列组的最低价格。我的预期输出如下:

Code          price1          price2      price3     vendor for price1      vendor for price 2      vendor for price 3

125           0.0011          0.0014      0.0050     Vendor3                Vendor1                 Vendor 2 
126           0.0019          0.0019      0.0034     Vendor3                Vendor2                 Vendor 1

那么获取这样的记录的MySQL查询是什么?而且我还必须进行查询以从表中获取最大值和第二个最高值,并且可能有任意数量的行包含单个代码。

我的数据位于此SQL Fiddle

在第二个最高值的情况下,输出应为:

Code          price1          price2      price3     vendor for price1      vendor for price 2      vendor for price 3
125           0.0012          0.0016      0.0054     Vendor1                Vendor2                 Vendor 1 
126           0.0025          0.0024      0.0065     Vendor1                Vendor1                 Vendor 2

4 个答案:

答案 0 :(得分:2)

以下是如何做到这一点

SELECT
  vender_prices.code,
  l.price1,
  r.price2,
  m.price3,
  l.vendor_name `Vender1`,
  r.vendor_name `Vender2`,
  m.vendor_name `Vender3`
FROM vender_prices
  LEFT JOIN (SELECT
               code, vendor_name, vender_prices.price1
             FROM vender_prices
               INNER JOIN (SELECT MIN(price1) AS price1 FROM vender_prices GROUP BY vender_prices.code) AS l
                 ON l.price1 = vender_prices.price1
             GROUP BY vender_prices.code
             ) as l ON vender_prices.code = l.code
  LEFT JOIN (SELECT
               code, vendor_name, vender_prices.price2
             FROM vender_prices
               INNER JOIN (SELECT MIN(price2) AS price2 FROM vender_prices GROUP BY vender_prices.code) AS l
                 ON l.price2 = vender_prices.price2
             GROUP BY vender_prices.code
             ) as r ON vender_prices.code = r.code
  LEFT JOIN (SELECT
               code, vendor_name, vender_prices.price3
             FROM vender_prices
               INNER JOIN (SELECT MIN(price3) AS price3 FROM vender_prices GROUP BY vender_prices.code) AS l
                 ON l.price3 = vender_prices.price3
             GROUP BY vender_prices.code
             ) as m ON vender_prices.code = m.code
GROUP BY vender_prices.code

SQL Fiddle Demo

输出

| CODE | PRICE1 | PRICE2 | PRICE3 |  VENDER1 |  VENDER2 |  VENDER3 |
--------------------------------------------------------------------
|  125 | 0.0011 | 0.0014 | 0.0050 | Vendor 3 | Vendor 1 | Vendor 2 |
|  126 | 0.0019 | 0.0019 | 0.0034 | Vendor 3 | Vendor 2 | Vendor 1 |

答案 1 :(得分:1)

SELECT
    data.*,
    v1.vendor_name 'vendor for price1',
    v2.vendor_name 'vendor for price2',
    v3.vendor_name 'vendor for price3'
FROM
    (
        SELECT
            Code,
            MIN(price1) price1,
            MIN(price2) price2,
            MIN(price3) price3
        FROM
            tbl
        GROUP BY Code
    ) data
    LEFT JOIN
    (
        SELECT 
            MIN(vendor_name) vendor_name,
            Code
        FROM
            tbl
        WHERE
            price1 = 
            (
                SELECT
                    MIN(price1)
                FROM
                    tbl t
                WHERE
                    t.Code = tbl.Code
            )
        GROUP BY Code
    ) v1 ON data.Code = v1.Code
    LEFT JOIN
    (
        SELECT 
            MIN(vendor_name) vendor_name
            Code
        FROM
            tbl
        WHERE
            price2 = 
            (
                SELECT
                    MIN(price2)
                FROM
                    tbl t
                WHERE
                    t.Code = tbl.Code
            )
        GROUP BY Code
    ) v2 ON data.Code = v2.Code
    LEFT JOIN
    (
        SELECT 
            MIN(vendor_name) vendor_name
            Code
        FROM
            tbl
        WHERE
            price3 = 
            (
                SELECT
                    MIN(price3)
                FROM
                    tbl t
                WHERE
                    t.Code = tbl.Code
            )
        GROUP BY Code
    ) v3 ON data.Code = v3.Code

即使查询本身看起来很大,但连接重复了3次。

更新我更新了删除LIMIT并添加MIN(vendor_name) vendor_name而不是vendor_name的查询。

演示

Here

输出

| CODE | PRICE1 | PRICE2 | PRICE3 | VENDOR FOR PRICE1 | VENDOR FOR PRICE2 | VENDOR FOR PRICE3 |
-----------------------------------------------------------------------------------------------
|  125 | 0.0011 | 0.0014 | 0.0050 |          Vendor 3 |          Vendor 1 |          Vendor 2 |
|  126 | 0.0019 | 0.0019 | 0.0034 |          Vendor 3 |          Vendor 2 |          Vendor 1 |

答案 2 :(得分:0)

试试这个:

select table1.vendor_name as vendor_name_for_price1,table2.vendor_name as vendor_name_for_price2, table3.vendor_name as vendor_name_for_price3

from 
table table1, table table2, table table3,
(Select code, min(price1),min(price2),min(price3) from table group by code ) TMP1

where
table1.price1=min(price1) and table1.code=TMP1.code
and
table2.price2=min(price2) and table2.code=TMP2.code
and
table3.price3=min(price3) and table3.code=TMP2.code ;

答案 3 :(得分:0)

这是一个很好的做法,我先尝试一种粗暴的方法。

select 1 as wh,code,min(price1) as price,vendor_name
from(
  select code,price1,vendor_name
  from ForgeRock
  order by code,price1
  )t1
group by code
union all
select 2 as wh,code,min(price2) as price,vendor_name
from(
  select code,price2,vendor_name
  from ForgeRock
  order by code,price2
  )t1
group by code
union all
select 3 as wh,code,min(price3) as price,vendor_name
from(
  select code,price3,vendor_name
  from ForgeRock
  order by code,price3
  )t1
group by code

这是一种非常简单易行的方法,无需加入, 我认为这足以使用了。 我添加了一列wh,你可以根据需要调整结果。 但是,使用上面的代码,你无法获得第二低的结果。 有几种方法可以达到这个目标, 我建议你尝试制作像:

这样的分区
CREATE TABLE ForgeRock
    (`unique_id` tinyint, `vendor_name` varchar(8), `price1` float(5,4)
    , `price2` float(5,4), `price3` float(5,4),`code` tinyint)
PARTITION BY KEY(code)
PARTITIONS 2;

INSERT INTO ForgeRock
    (`unique_id`, `vendor_name`, `price1`, `price2`, `price3`, `code`)
VALUES
(1,'Vendor 1',0.0012,0.0014,0.0054,125),
(2,'Vendor 2',0.0015,0.0016,0.0050,125),
(3,'Vendor 3',0.0011,0.0019,0.0088,125),
(4,'Vendor 1',0.0025,0.0024,0.0034,126),
(5,'Vendor 2',0.0043,0.0019,0.0065,126),
(6,'Vendor 3',0.0019,0.0085,0.0082,126);

这有点棘手,但如果code中没有这么多不同的值,那么非常有用。 你可以得到结果:

select * from
(select code,price1 as price,vendor_name
from ForgeRock partition (p0)
order by price1
Limit 1,1
)t1
union all
select * from
(select code,price1 as price,vendor_name
from ForgeRock partition (p1)
order by price1
Limit 1,1
)t1
union all
select * from
(select code,price2 as price,vendor_name
from ForgeRock partition (p0)
order by price2
Limit 1,1
)t1
union all
select * from
(select code,price2 as price,vendor_name
from ForgeRock partition (p1)
order by price2
Limit 1,1
)t1
union all
select * from
(select code,price3 as price,vendor_name
from ForgeRock partition (p0)
order by price3
Limit 1,1
)t1
union all
select * from
(select code,price3 as price,vendor_name
from ForgeRock partition (p1)
order by price3
Limit 1,1
)t1

虽然我认为你可以明显改善我的答案, 我会把这份工作留给你。