MySQL:查询并不总是返回多个商店中最低的最近价格

时间:2016-01-21 02:05:22

标签: mysql function min

如果只有单个商店的价格信息,下面的SQL会返回每个产品的最低价格,如果有超过一个商店的价格信息,则不会总是返回最新的最低价格!?< / p>

通缉结果

从所有商店的最新价格信息中返回产品的最低价格,因此,如果有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本身看起来效果很好并且只返回一个价格,现在的问题是如果我将select语句添加到函数中它会给出以下错误,即使我只看到当我自己运行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 ;

2 个答案:

答案 0 :(得分:2)

我倾向于使用一系列内部联接来获取结果集,而不是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

答案 1 :(得分:1)

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

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