5

这里的目标是: 1. 从 EACH 商店中为每种成分获取具有最近日期的行。2. 根据这个结果,比较价格以找到每种成分最便宜的商店。

我可以在单独的查询中完成第一个或第二个目标,但不能在同一个查询中完成。我如何过滤掉一个选择,然后对以前的结果应用另一个过滤器?

编辑:我从 MAX 和 MIN 获得的结果一直存在问题,因为它只是任意获取其余数据。为了避免这种情况,我应该在多个列上加入表(我猜)。我不确定这将如何处理重复的日期等。

我已经包含了查询的图像及其输出数据。

在此处输入图像描述

如果我们以成分 1 为例,它存在于三个不同的商店中(在不同日期两次在一个商店中)。

在这种情况下,成分 1 的最便宜当前价格将是 store3。如果日期为 2013-05-25 的第四行更便宜,它仍然不会“获胜”,因为它已经过时了。(忽略品牌名称,它们在这个问题上并不重要。)

非常感谢您提供的任何帮助/意见!

4

3 回答 3

1

这可能需要将几个子查询连接在一起。

这没有经过测试(因为我没有你的表定义,也没有任何测试数据),但是像这样:-

SELECT i.name AS ingredient,
        ip.price,
        ip.date,
        s.name AS storename,
        b.name AS brandname
FROM ingredient i
INNER JOIN ingredient_price ip
ON ingredient.ingredient_id = ingredient_price.ingredient_id
INNER JOIN store_to_ingredient_price stip
ON ingredient_price.ingredient_price_id = store_to_ingredient_price.ingredient_price_id
INNER JOIN store s 
ON store_to_ingredient_price.store_id = store.store_id
INNER JOIN brand_to_ingredient_price btip
ON ingredient_price.ingredient_price_id = brand_to_ingredient_price.ingredient_price_id
INNER JOIN brand b
ON brand_to_ingredient_price.brand_id = brand.brand_id  
INNER JOIN  
(
    SELECT i.ingredient_id,
            stip.store_id,
            ip.date,
            MIN(ip.price) AS lowest_price
    FROM ingredient i
    INNER JOIN ingredient_price ip
    ON ingredient.ingredient_id = ingredient_price.ingredient_id
    INNER JOIN store_to_ingredient_price stip
    ON ingredient_price.ingredient_price_id = store_to_ingredient_price.ingredient_price_id
    INNER JOIN
    (
        SELECT i.ingredient_id,
                stip.store_id,
                MAX(ip.date) AS latest_date
        FROM ingredient i
        INNER JOIN ingredient_price ip
        ON ingredient.ingredient_id = ingredient_price.ingredient_id
        INNER JOIN store_to_ingredient_price stip
        ON ingredient_price.ingredient_price_id = store_to_ingredient_price.ingredient_price_id
        GROUP BY ingredient_id, store_id
    ) Sub1
    ON i.ingredient_id = Sub1.ingredient_id
    AND stip.store_id = Sub1.store_id
    AND ip.date = Sub1.latest_date
    GROUP BY i.ingredient_id, stip.store_id, ip.date
) Sub2
ON  i.ingredient_id = Sub2.ingredient_id
AND stip.store_id = Sub2.store_id
AND ip.date = Sub2.date
AND ip.price = Sub2.lowest_price
于 2014-03-20T12:15:41.653 回答
1

这个问题真的很有趣!

因此,首先,我们从 EACH 商店获取每种成分的最新日期的行。(每家商店的最新日期可能不同。)然后,我们比较每家商店的价格(无论日期如何),以找到每种成分的最低价格。

下面的查询很好地使用了 GROUP_CONCAT 函数。这是一个关于使用该功能的问题。

SELECT
   i.name as ingredient_name
  , MIN(store_price.price) as price
  , SUBSTRING_INDEX(
    GROUP_CONCAT(store_price.date ORDER BY store_price.price),
    ',',
    1
    ) as date
  , SUBSTRING_INDEX(
    GROUP_CONCAT(s.name ORDER BY store_price.price),
    ',',
    1
    ) as store_name
  , SUBSTRING_INDEX(
    GROUP_CONCAT(b.name ORDER BY store_price.price),
    ',',
    1
    ) as brand_name
FROM
  ingredient i
JOIN
(SELECT
  ip.ingredient_id as ingredient_id
  , stip.store_id as store_id
  , btip.brand_id as brand_id
  , CONVERT(SUBSTRING_INDEX(
    GROUP_CONCAT(ip.ingredient_price_id ORDER BY ip.date DESC),
    ',',
    1
    ), UNSIGNED INTEGER) as ingredient_price_id
  , MAX(ip.date) as date
  , CONVERT(SUBSTRING_INDEX(
    GROUP_CONCAT(ip.price ORDER BY ip.date DESC),
    ',',
    1
    ), DECIMAL(5,2)) as price
FROM ingredient_price ip
JOIN store_to_ingredient_price stip ON ip.ingredient_price_id = stip.ingredient_price_id
JOIN brand_to_ingredient_price btip ON ip.ingredient_price_id = btip.ingredient_price_id
GROUP BY 
  ip.ingredient_id
  , stip.store_id) store_price
ON i.ingredient_id = store_price.ingredient_id
JOIN store s ON s.store_id = store_price.store_id
JOIN brand b ON b.brand_id = store_price.brand_id
GROUP BY
  store_price.ingredient_id;

您可以检查此SQL Fiddle上的实现。

下面的版本忽略了品牌,略小:

SELECT
   i.name as ingredient_name
  , MIN(store_price.price) as price
  , SUBSTRING_INDEX(
    GROUP_CONCAT(store_price.date ORDER BY store_price.price),
    ',',
    1
    ) as date
  , SUBSTRING_INDEX(
    GROUP_CONCAT(s.name ORDER BY store_price.price),
    ',',
    1
    ) as store_name
FROM
  ingredient i
JOIN
(SELECT
  ip.ingredient_id as ingredient_id
  , stip.store_id as store_id
  , CONVERT(SUBSTRING_INDEX(
    GROUP_CONCAT(ip.ingredient_price_id ORDER BY ip.date DESC),
    ',',
    1
    ), UNSIGNED INTEGER) as ingredient_price_id
  , MAX(ip.date) as date
  , CONVERT(SUBSTRING_INDEX(
    GROUP_CONCAT(ip.price ORDER BY ip.date DESC),
    ',',
    1
    ), DECIMAL(5,2)) as price
FROM ingredient_price ip
JOIN store_to_ingredient_price stip ON ip.ingredient_price_id = stip.ingredient_price_id
GROUP BY 
  ip.ingredient_id
  , stip.store_id) store_price
ON i.ingredient_id = store_price.ingredient_id
JOIN store s ON s.store_id = store_price.store_id
GROUP BY
  store_price.ingredient_id;

参考: 在 MySQL 中模拟 First/Last 聚合函数

于 2014-03-21T02:41:44.413 回答
0

试试这个:

SELECT  `newest`.ingredient, `newest`.store,
        `newest`.brand, `newest`.price, `newest`.`latest_date`
FROM
        (SELECT         ingredient.name AS ingredient, store.name AS store,
                        brand.name AS brand, ingredient_price.price,
                        MAX( ingredient_price.date ) AS `latest_date`
        FROM            ingredient
        LEFT OUTER JOIN ingredient_price
            ON ingredient.ingredient_id = ingredient_price.ingredient_id
        LEFT OUTER JOIN store_to_ingredient_price
            ON ingredient_price.ingredient_price_id = store_to_ingredient_price.ingredient_price_id
        LEFT OUTER JOIN store
            ON store_to_ingredient_price.store_id = store.store_id
        LEFT OUTER JOIN brand_to_ingredient_price
            ON ingredient_price.ingredient_price_id = brand_to_ingredient_price.ingredient_price_id
        LEFT OUTER JOIN brand
            ON brand_to_ingredient_price.brand_id = brand.brand_id
        GROUP BY ingredient.name) `newest`

ORDER BY `newest`.price
LIMIT 1
于 2013-09-09T14:32:55.893 回答