SQL - 多 SELECT 和 GROUP BY 以获取表的 MIN(value)

Posted

技术标签:

【中文标题】SQL - 多 SELECT 和 GROUP BY 以获取表的 MIN(value)【英文标题】:SQL - multi SELECT and GROUP BY to get MIN(value) of table 【发布时间】:2021-03-14 09:39:39 【问题描述】:

我正在开发一个价格比较网站。

我有以下表格: 表 item_price:

|| Set_id ||store_id ||currency_id ||set_price ||
||  5252  ||    1    ||     1      ||   499.99 ||
||  5252  ||    2    ||     1      ||   480    ||
||  5252  ||    3    ||     1      ||   489    ||
||  5252  ||    4    ||     2      ||   450    ||
||  5252  ||    5    ||     2      ||   445    ||
||  5252  ||    6    ||     2      ||   470    ||
||  5253  ||    1    ||     1      ||   389.99 ||
||  5253  ||    2    ||     1      ||   392    ||
||  5253  ||    3    ||     1      ||   400    ||
||  5253  ||    4    ||     2      ||   360    ||
||  5253  ||    5    ||     2      ||   370    ||
||  5253  ||    6    ||     2      ||   380    ||

和设置货币

||currency_id||currency_name||conversion_rate||
||    1      ||    EUR      ||      1        ||
||    1      ||    GBP      ||      0.9      ||

我的目标是获得一个查询,以下列格式返回每种货币的最便宜价格

|| Set_id || store_id || Min_price_eur || Min_price_gbp_in_eur ||
||  5252  ||    5     ||      480      ||        400.5         ||
||  5253  ||    4     ||    389.99     ||        324           ||


到目前为止,我只实现了一半的目标:

|| Set_id || store_id || Min_price_eur ||
||  5252  ||    1     ||      480      ||
||  5253  ||    1     ||      392      ||

使用以下请求:

SELECT 
    set_id,
    min(set_price) AS Min_price_eur,

FROM `item_price`
WHERE currency_id=1
GROUP BY set_id

为了创建最后一列,我厌倦了很多事情,例如:

SELECT 
    set_id,
    min(set_price) AS Min_price_eur,
    (SELECT MIN(set_price) FROM 'item_price' WHERE currency_id=2) * (SELECT conversion_rate FROM set_currency WHERE currency_id = 2) AS  Min_price_gbp_in_eur

FROM `item_price`
WHERE currency_id=1
GROUP BY set_id

但我不会。 如果有人能给我一些帮助,我将不胜感激。

谢谢

ps: 以下是创建表格的代码:

商品价格:

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET AUTOCOMMIT = 0;
START TRANSACTION;
SET time_zone = "+00:00";


CREATE TABLE `item_price` (
  `set_id` int(10) UNSIGNED NOT NULL,
  `store_id` int(10) UNSIGNED NOT NULL,
  `currency_id` int(10) UNSIGNED NOT NULL,
  `set_price` float UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;



INSERT INTO `item_price` (`set_id`, `store_id`, `currency_id`, `set_price`) VALUES
(5252, 1, 1, 499.99),
(5252, 2, 1, 480),
(5252, 3, 1, 489),
(5252, 4, 2, 450),
(5252, 5, 2, 445),
(5252, 6, 2, 470),
(5253, 1, 1, 389.55),
(5253, 2, 1, 392),
(5253, 3, 1, 400),
(5253, 4, 2, 360),
(5253, 5, 2, 370),
(5253, 6, 2, 380);


ALTER TABLE `item_price`
  ADD PRIMARY KEY (`set_id`,`store_id`) USING BTREE,
  ADD KEY `store_id` (`store_id`),
  ADD KEY `currency_id` (`currency_id`);
COMMIT;

和 货币:

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET AUTOCOMMIT = 0;
START TRANSACTION;
SET time_zone = "+00:00";



CREATE TABLE `set_currency` (
  `currency_id` int(10) UNSIGNED NOT NULL,
  `currency_name` char(3) NOT NULL,
  `conversion_rate` float UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


INSERT INTO `set_currency` (`currency_id`, `currency_name`, `conversion_rate`) VALUES
(1, 'EUR', 1),
(2, 'GBP', 0.9);

ALTER TABLE `set_currency`
  ADD PRIMARY KEY (`currency_id`);
COMMIT;

【问题讨论】:

当您想要最便宜的英镑价格时,您是只想查看实际货币为英镑 (currency_id = 2) 的记录还是要将价格转换为其他货币(欧元)英镑并将它们也包括在支票中? (英镑和欧元互换角色时也是如此。) @stickybit,当我想要最便宜的英镑价格(Min_price_gbp_in_eur)时,我只想查看货币实际为英镑(currency_id = 2)的记录,并以欧元表示。你提供给我的第二个选择将是我的长期目标......让 sql 为我带来所有价格和货币中每件商品的最便宜的价格 ||设置_id || store_id || Min_price_eur_accross_all_shops_and_currencies||但是,老实说,我不知道从哪里开始在 SQL 中执行此操作。这不是问题,因为我从查询结果中在 php 中管理它。很高兴学习! 不清楚。在所需的输出store_id=1 中为Set_id=5252。在查看源数据时,Min_price_eur=480 正确匹配,而 Min_price_gbp_in_eur=400.5 匹配 store_id=5。 ??? 你使用什么版本的 mysql @Akina 很好发现,我已修复)) Min_price_gbp_in_eur=400.5 适用于 store_id=5 ,这是正确的 (445*0.9) 【参考方案1】:

这个问题对我来说看起来像是用一些算术聚合:

select ip.set_id, ip.store_id,
       min(case when currency_name = 'EUR' then ip.set_price end) as min_price_eur,
       min(case when currency_name = 'GBP' then ip.set_price / c.conversion_rate end) as min_gpbprice_eur
from item_price ip left join
     set_currency c
     on ip.currency_id = c.currency_id
group by ip.set_id, ip.store_id

【讨论】:

(ip.set_id, ip.store_id) 在源数据中似乎是独一无二的(实际上可能是(ip.set_id, ip.store_id, currency_id))。所以这个表达式的 GROUP BY 看起来很奇怪。 谢谢戈登。这使我离正在寻找的答案更近了几步……但是,您的查询为我带来了以欧元为单位的所有商店价值。不仅是最便宜的,还有与之匹配的 store_id... @Quiche 。 . .我认为这就是您想要的:“我的目标是获得一个查询,以下列格式为我带来每种货币的最便宜价格”。也许你应该问另一个更具体的问题。 @Gordon,不,正如我所说,它帮助了我,通过满足您的要求,我设法得到了我想要的东西,并且还意识到我可以优化我正在寻找的东西 :)(原因我“检查”了你的答案)。您是否知道是否有一种方法可以在一个请求中提供最低价格(在 min_price_eur 和 min_price_gbp_in_eur 之外?)? (否则,我很好,我已经在 php 中的 sql 之外进行操作)

以上是关于SQL - 多 SELECT 和 GROUP BY 以获取表的 MIN(value)的主要内容,如果未能解决你的问题,请参考以下文章

SQL如何使用order by语句查询数据表的多字段

玩转SQL语句之group by 多字段分组查询与having子句,一篇解决你的疑惑!

sql语句中的group by啥意思

sql语句中的group by要怎么用!!

sql语句select group by order by where一般先后顺序

sql语句select group by order by where一般先后顺序