簡體   English   中英

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

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

我正在尋找一個快速的MySQL查詢,該查詢返回與所有價格類別( a, b, cd )相比價格最低( min )或價格最高( max )的產品ID

我有一個名為chocolate_stock的產品表,其中包含幾個價格類別。 從特定類別( 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   
--------------------------------------------------------------

價格類別為decimal(10,2) 這是一個從類別中返回最高價格的示例, 但未返回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)) .")";

檢索此信息的最快方法是什么?

如果要制表一下您希望輸出的外觀可能會有所幫助,但是我認為您缺少的是HAVING子句。

首先-試試這個

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

然后嘗試

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)

此查詢可滿足您的需求:

(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)

如果您在id上有一個索引,它應該會表現良好。

該方法需要遍歷表四次(盡管id上的索引應大大減少該次數)。 以下方法僅需要遍歷表一次:

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 . . .

它使用一個帶有group_concat()substring_index()的技巧來獲取每個列的最大id。

您要做的第一件事是規范化數據,為了便於以后查詢,我將創建以下視圖:

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;

然后我不確定您想要的格式,如果您想要每個價格的最小值和最大值,您可以使用以下格式:

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;

它將從您的樣本數據中輸出以下內容:

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

但是,如果它只是所有價格(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;

將輸出以下內容:

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

SQL小提琴上的示例

試試看,它模擬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)) .")

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

您沒有得到id,因為MAX返回一個值。 但是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)).")";

等等

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM