我有一个产品和一个价格表(包含产品 ID、价格和时间戳列)。现在我需要加入简单选择的最新价格的产品。
简单连接将选择表中第一个保存的价格,但不是最新的。
SELECT p.*, pp.price
FROM products p
INNER JOIN product_prices pp ON (pp.product_id = p.id)
所以我尝试加入选择最新的时间戳,但这只会返回所有记录的最新时间戳,而不是每个产品价格:
SELECT p.*, pp.*
FROM products p
LEFT JOIN
(SELECT product_id, ranking, MAX(timestamp) as timestamp
FROM product_prices) pp
ON pp.product_id = p.id
是否有一种聪明/正确的方法来选择每个产品具有最新价格的所有产品?
你已经很接近了,但是你需要在子查询中使用
GROUP BY
:
SELECT p.*, pp.*
FROM products p LEFT JOIN
(SELECT product_id, MAX(timestamp) as timestamp
FROM product_prices
GROUP BY product_id
) pp
ON pp.product_id = p.id;
不清楚
ranking
专栏是关于什么的。 它仅在您的查询中使用,在问题的其他地方未提及。
如果您想要整个
product_price
行,您可以使用额外的 JOIN
:
SELECT p.*, pp.*
FROM products p JOIN
product_prices pp
ON pp.product_id = p.id LEFT JOIN
(SELECT product_id, MAX(timestamp) as timestamp
FROM product_prices
GROUP BY product_id
) ppm
ON ppm.product_id = p.id AND ppm.timestamp = pp.timestamp;
我认为你需要two加入这里。 第一个连接直接连接到
product_prices
表,以从该表中引入所需的列。 第二个连接是子查询,该子查询按产品聚合 product_prices
,以查找每个产品的最新条目。 然后,第二次连接会限制来自第一次连接的完整结果。
SELECT p.*, pp1.*
FROM products p
LEFT JOIN product_prices pp1
ON p.id = pp1.product_id
INNER JOIN
(
SELECT product_id, MAX(timestamp) AS max_ts
FROM product_prices
GROUP BY product_id
) pp2
ON pp1.product_id = pp2.product_id AND
pp1.timestamp = pp2.max_ts;
如果您使用 MySQL 8+,那么我们可以在这里利用窗口函数:
WITH cte AS (
SELECT p.*, pp1.*,
ROW_NUMBER() OVER (PARTITION BY p.id ORDER BY pp.timestamp DESC) rn
FROM products p
LEFT JOIN product_prices pp
ON p.id = pp.product_id
)
SELECT *
FROM cte
WHERE rn = 1;
请使用RANK功能获取产品的最新价格。
例如:
SELECT
pp.product_id, pp.timestamp, pp.price,
RANK() OVER(PARTITION BY pp.product_id ORDER BY pp.timestamp DESC) Rnk
FROM product_prices pp
WHERE pp.Rnk = 1
您还可以加入您的产品表:
SELECT
p.id, p.description, pp.timestamp, pp.price,
RANK() OVER(PARTITION BY pp.product_id ORDER BY pp.timestamp DESC) Rnk
FROM products p
JOIN product_prices pp ON pp.product_id = p.id
WHERE pp.Rnk = 1