[英]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, c
和d
)相比价格最低( 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
). 从特定类别( a
或b
或c
或d
)获得最低( 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
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.