简体   繁体   English

SELECT ID,其中多列的最小值或最大值

[英]SELECT id where min or max value from multiple columns

I'm looking for a fast MySQL query that returns the id of the product with the lowest ( min ) or highest ( max ) price, compared to all price categories ( a, b, c and d ). 我正在寻找一个快速的MySQL查询,该查询返回与所有价格类别( a, b, cd )相比价格最低( min )或价格最高( max )的产品ID

I have a product table called chocolate_stock with several price categories. 我有一个名为chocolate_stock的产品表,其中包含几个价格类别。 It's pretty easy to receive the lowest ( min ) or highest ( max ) price from a specific category ( a or b or c or d ). 从特定类别( abcd )获得最低( min )或最高( max )价格是很容易的。

id |      name       | price_a | price_b | price_c | price_d |
--------------------------------------------------------------
1  |   Chips Ahoy    |   250   |   530   |   720   |   120 
--------------------------------------------------------------
2  | Chocolate Chunk |   250   |   90    |  32.92  |   110   
--------------------------------------------------------------
3  |      Oreo       |   103   |  44.52  |   250   |   850   
--------------------------------------------------------------

The price categories are decimal(10,2) . 价格类别为decimal(10,2) Here's a sample that returns the highest price from the categories, but not the id: 这是一个从类别中返回最高价格的示例, 但未返回ID:

$t = 'chocolate_stock';
$arrIds = array(1, 3);

$strQuery = "SELECT id, 
             MAX(price_a) AS price_a, 
             MAX(price_b) AS price_b, 
             MAX(price_c) AS price_c, 
             MAX(price_d) AS price_d 
             FROM $t WHERE id IN(". implode(',', array_map('intval', $arrIds)) .")";

What is the fastest way to retrieve this information? 检索此信息的最快方法是什么?

It might help if you were to tabulate what you want your output to look like, but I think the piece you are missing is the HAVING clause. 如果要制表一下您希望输出的外观可能会有所帮助,但是我认为您缺少的是HAVING子句。

first - try this 首先-试试这个

select min(id), max(price_a) from $t having price_a = max(price_a)

Then try 然后尝试

select min(id), min(price_a) from $t having price_a = min(price_a)
union
select min(id), max(price_a) from $t having price_a = max(price_a)

This query does what you want: 此查询可满足您的需求:

(select t.*
 from $t t
 where . . .
 order by price_a desc
 limit 1) union all
 (select t.*
 from $t t
 where . . .
 order by price_b desc
 limit 1) union all
(select t.*
 from $t t
 where . . .
 order by price_c desc
 limit 1) union all
(select t.*
 from $t t
 where . . .
 order by price_d desc
 limit 1)

If you have an index on id it should perform reasonably well. 如果您在id上有一个索引,它应该会表现良好。

That approach requires four passes through the table (although the index on id should greatly reduce that). 该方法需要遍历表四次(尽管id上的索引应大大减少该次数)。 The following approach requires only one pass through the table: 以下方法仅需要遍历表一次:

select MAX(price_a),
       substring_index(group_concat(id order by price_a desc), ',', 1),
       max(price_b),
       substring_index(group_concat(id order by price_b desc), ',', 1),
       max(price_c),
       substring_index(group_concat(id order by price_c desc), ',', 1),
       max(price_d),
       substring_index(group_concat(id order by price_d desc), ',', 1)
from $t
where . . .

It uses a trick with group_concat() and substring_index() to get the max id for each of the columns. 它使用一个带有group_concat()substring_index()的技巧来获取每个列的最大id。

The first thing you would want to do is normalise your data, for ease of later querying I would create the following view: 您要做的第一件事是规范化数据,为了便于以后查询,我将创建以下视图:

CREATE VIEW NormalT
AS
    SELECT  ID, Name, 'Price_a' AS Type, Price_a AS Price
    FROM    T
    UNION ALL
    SELECT  ID, Name, 'Price_b' AS Type, Price_b AS Price
    FROM    T
    UNION ALL
    SELECT  ID, Name, 'Price_c' AS Type, Price_c AS Price
    FROM    T
    UNION ALL
    SELECT  ID, Name, 'Price_d' AS Type, Price_d AS Price
    FROM    T;

Then I am not sure of the format you want, if you want the min an max for each price you could use this: 然后我不确定您想要的格式,如果您想要每个价格的最小值和最大值,您可以使用以下格式:

SELECT  mt.Type2,
        mt.Type,
        mt.Price,
        t.ID,
        t.Name
FROM    (   SELECT  Type, MIN(Price) AS Price, 'MIN' AS Type2
            FROM    NormalT
            GROUP BY Type
            UNION ALL
            SELECT  Type, MAX(Price) AS Price, 'MAX' AS Type2
            FROM    NormalT
            GROUP BY Type
        ) mt
        INNER JOIN NormalT T
            ON mt.Type = T.Type
            AND mt.Price = t.Price
ORDER BY mt.Type2, mt.Type, t.ID;

Which will output the following from your sample data: 它将从您的样本数据中输出以下内容:

TYPE2   TYPE        PRICE   ID  NAME
MAX     Price_a     250     1   Chips Ahoy
MAX     Price_a     250     2   Chocolate Chunk
MAX     Price_b     530     1   Chips Ahoy
MAX     Price_c     720     1   Chips Ahoy
MAX     Price_d     850     3   Oreo
MIN     Price_a     103     3   Oreo
MIN     Price_b     44.52   3   Oreo
MIN     Price_c     32.92   2   Chocolate Chunk
MIN     Price_d     110     2   Chocolate Chunk

However, if it is just the min and max of all prices (a, b, c and d) then you could use this: 但是,如果它只是所有价格(a,b,c和d)的最小值和最大值,则可以使用以下方法:

SELECT  mt.Type2,
        t.Type,
        mt.Price,
        t.ID,
        t.Name
FROM    (   SELECT  MIN(Price) AS Price, 'MIN' AS Type2
            FROM    NormalT
            UNION ALL
            SELECT  MAX(Price) AS Price, 'MAX' AS Type2
            FROM    NormalT
        ) mt
        INNER JOIN NormalT T
            ON mt.Price = t.Price;

Which will output this: 将输出以下内容:

TYPE2   TYPE    PRICE       ID  NAME
MIN     Price_c     32.92   2   Chocolate Chunk
MAX     Price_d     850     3   Oreo

Examples on SQL Fiddle SQL小提琴上的示例

Try this , It's emulating Analytics as MYSQL doesn't have them by default : 试试看,它模拟Analytics(分析),因为默认情况下MYSQL没有它们:

SELECT id, 
             ( select MAX(price_a) from $t t2 where  t2.id = t1.id ) AS price_a, 
             ( select MAX(price_b) from $t t2 where  t2.id = t1.id ) AS price_b, 
             ( select MAX(price_c) from $t t2 where  t2.id = t1.id ) AS price_c, 
             ( select MAX(price_d) from $t t2 where  t2.id = t1.id ) AS price_d 
             FROM $t t1 WHERE id IN(". implode(',', array_map('intval', $arrIds)) .")

Source From : http://www.oreillynet.com/pub/a/mysql/2007/03/29/emulating-analytic-aka-ranking-functions-with-mysql.html?page=3 资料来源: http : //www.oreillynet.com/pub/a/mysql/2007/03/29/emulating-analytic-aka-ranking-functions-with-mysql.html?page=3

You are not getting id because, MAX returns one value. 您没有得到id,因为MAX返回一个值。 But it is not so with id.You can use seperate queries like 但是id并非如此。您可以使用单独的查询,例如

SELECT id,MAX(price_a) FROM $t WHERE id IN (". implode(',', array_map('intval', $arrIds)).")";
SELECT id,MAX(price_b) FROM $t WHERE id IN (". implode(',', array_map('intval', $arrIds)).")";

etc 等等

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM