【问题标题】:MySQL: Query not always returning lowest most recent price across multiple storesMySQL:查询并不总是返回多个商店的最低最新价格
【发布时间】:2016-04-27 03:10:34
【问题描述】:

如果只有一个商店的价格信息,下面的 SQL 将返回每个产品的最近最低价格,如果有多个商店的价格信息,则并不总是返回最近的最低价格!?

想要的结果

从所有商店的最新价格信息中返回产品的最低价格,因此如果有 6 家商店,它将显示 6 家商店中每家商店最近价格记录中的最低价格。

如果所有商店价格记录的最新价格相同且更新日期也相同,则可以按商店订购记录以选择相关产品的价格。

{product id} 是传入的值,具体取决于所显示的产品。

SQL

SELECT `vsp`.`prod_id`
, `vsp`.`price`
, `vsp`.`store`
, `vsp`.`updated`
FROM `price` `vsp`
WHERE NOT EXISTS
(
    SELECT * 
    FROM `price` `vsp2`
    WHERE `vsp2`.`prod_id` = `vsp`.`prod_id`
    AND `vsp`.`prod_id` = {product id}
    AND (`vsp2`.`updated` > `vsp`.`updated` OR (`vsp2`.`updated` = `vsp`.`updated` AND `vsp2`.`price` < `vsp`.`price`))
) AND `vsp`.`prod_id` = {product id}

价格

prod_id     | price     | store | updated
--------------------------------------------------------
product 1   | 1.99      | 1     | 2016-01-20 00:00:00
product 2   | 1.49      | 1     | 2016-01-20 00:10:00
product 2   | 1.19      | 2     | 2016-01-20 00:00:00
product 3   | 12.49     | 1     | 2016-01-20 00:00:00
product 3   | 12.49     | 2     | 2016-01-20 00:00:00
product 4   | 9.89      | 1     | 2016-01-20 00:00:00
product 5   | 10.00     | 1     | 2016-01-20 00:10:00
product 5   | 9.99      | 2     | 2016-01-20 00:00:00
product 5   | 10.49     | 3     | 2016-01-20 00:00:00

预期输出

product 1   | 1.99      | 1     | 2016-01-20 00:00:00
product 2   | 1.49      | 1     | 2016-01-20 00:10:00
product 3   | 12.49     | 1     | 2016-01-20 00:00:00
product 4   | 9.89      | 1     | 2016-01-20 00:00:00
product 5   | 9.99      | 2     | 2016-01-20 00:00:00

电流输出

product 1   | 1.99      | 1     | 2016-01-20 00:00:00
product 2   | 1.49      | 1     | 2016-01-20 00:10:00
product 3   | 12.49     | 1     | 2016-01-20 00:00:00
product 4   | 9.89      | 1     | 2016-01-20 00:00:00
product 5   | 10.00     | 1     | 2016-01-20 00:10:00

更新 #1

当我将 prodId 约束添加到查询中时,选择本身看起来工作得很好,并且只返回一个价格,现在的问题是,如果我将 select 语句添加到函数中,它会给出以下错误,即使我只看到我自己运行选择时返回的一个值。

Result consisted of more than one row

SQL 函数

CREATE FUNCTION FN_GET_SET_LOWEST_PRICE (`prodId` VARCHAR(20))
RETURNS DOUBLE
BEGIN
    DECLARE `latestPrice` DOUBLE(7,2) DEFAULT 0;

    SELECT p3.price
    INTO `latestPrice`
    FROM price p3
    INNER JOIN
    (
        SELECT p1.prod_id, MIN(p1.price) AS minPrice
        FROM price p1
        INNER JOIN
        (
            SELECT prod_id, MIN(updated) AS minUpdated
            FROM price
            GROUP BY prod_id
        ) p2
        ON p1.prod_id = p2.prod_id AND p1.updated = p2.minUpdated
        GROUP BY p1.prod_id
    ) t
    ON p3.prod_id = t.prod_id AND p3.price = t.minPrice
    WHERE p3.prod_id = prodId;

    RETURN `latestPrice`;
END//
DELIMITER ;

【问题讨论】:

  • 如果您用简单的英语告诉我们,在product 有多个记录的情况下,决定保留哪条product 记录的逻辑是什么,我认为这可能会对我们有所帮助在price 表中。
  • @TimBiegeleisen,感谢您的反馈,我已将wanted outcome sn-p 添加到问题中以尝试弄清楚我正在尝试做的事情。
  • 您如何决定为 product 3 保留存储 1 而不是存储 2?如何处理这种平局情况?
  • @TimBiegeleisen,我从来没有发现过,但是是的,这是另一个没有考虑到的情况,我想说我可以在那种情况下按商店订购,但不确定这会如何影响整体我正在努力达到的结果。
  • 在我花了 45 分钟回答您的问题时,请随时为我投票。

标签: mysql function min


【解决方案1】:

我倾向于使用一系列内连接来获取您的结果集,而不是在难以阅读的 WHERE 子句中使用复杂的子查询。

SELECT p3.prod_id, p3.price, p3.store, p3.updated
FROM price p3
INNER JOIN
(
    SELECT p1.prod_id, MIN(p1.price) AS minPrice
    FROM price p1
    INNER JOIN
    (
        SELECT prod_id, MIN(updated) AS minUpdated
        FROM price
        GROUP BY prod_id
    ) p2
    ON p1.prod_id = p2.prod_id AND p1.updated = p2.minUpdated
    GROUP BY p1.prod_id
) t
ON p3.prod_id = t.prod_id AND p3.price = t.minPrice

点击以下链接查看正在运行的演示:

SQLFiddle

更新:

如果你想像函数一样使用这个查询,那么你必须创建一个存储过程。原因是函数必须只返回一个值。即使你设计了一个应该只返回一个值的查询,MySQL 仍然会报错。

尝试以下方法:

CREATE PROCEDURE FN_GET_SET_LOWEST_PRICE(prodId VARCHAR(20))
BEGIN
    SELECT p3.price
    FROM price p3
    INNER JOIN
    (
        SELECT p1.prod_id, MIN(p1.price) AS minPrice
        FROM price p1
        INNER JOIN
        (
            SELECT prod_id, MIN(updated) AS minUpdated
            FROM price
            GROUP BY prod_id
        ) p2
        ON p1.prod_id = p2.prod_id AND p1.updated = p2.minUpdated
        GROUP BY p1.prod_id
    ) t
    ON p3.prod_id = t.prod_id AND p3.price = t.minPrice
    WHERE p3.prod_id = prodId;
END

【讨论】:

  • 通过一些快速测试看起来运行正常。最后一个问题,如果我将该查询放入一个返回双精度的函数中,它会给出说你不能返回结果集,有什么想法吗?
  • 这个错误不是不言自明吗?该查询返回多条记录,每条记录都包含来自多列的值。如果您想在函数中使用它,我相信您必须将其配置为返回单个值。这可以使用 WHERE 子句以及单个列值的 SELECT 来完成。
  • 我使用ẀHERE 子句在p3.prod_id 上添加了一个约束,它选择返回一个正确的价格,但在函数中它给出了关于返回单行的信息,我已经用详细信息更新了原始问题,感谢您迄今为止的帮助!
  • 我昨天说错了。 MySQL 函数显然不能从查询中返回 any 结果集,因为无法确定它是否真的会返回单个值。您必须改用存储过程。
  • 刚刚注意到 SQL SQLFiddle 的一个问题,这应该只选择相同价格和更新日期的实例中的第一条记录,这可能是函数给出超过一行的原因按产品退回。
【解决方案2】:

我想这就是你真正想要的:

1 - find the last updated
2 - find the cheapest if last updated is multiple

这里是 SQL:

SELECT price.*
FROM price, (
    SELECT price.prod_id, last_price.max_updated, min(price.price) min_price
    FROM price, (
        SELECT prod_id,max(updated) max_updated 
        FROM price
        GROUP BY 1
    ) as last_price
    WHERE price.prod_id = last_price.prod_id
    AND   price.updated = last_price.max_updated
    GROUP BY 1,2
) as lowest_price
WHERE price.prod_id = lowest_price.prod_id
AND   price.updated = lowest_price.max_updated
AND   price.price   = lowest_price.min_price

【讨论】:

    猜你喜欢
    • 2016-04-25
    • 2013-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-07
    • 2017-12-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多