【问题标题】:MySQL LEFT JOIN, GROUP BY and ORDER BY not working as requiredMySQL LEFT JOIN、GROUP BY 和 ORDER BY 未按要求工作
【发布时间】:2011-06-02 14:27:31
【问题描述】:

我有一张桌子

'products' => ('product_id', 'name', 'description') 

还有一张桌子

'product_price' => ('product_price_id', 'product_id', 'price', 'date_updated')

我想执行类似的查询

SELECT `p`.*, `pp`.`price` 
FROM `products` `p` 
LEFT JOIN `product_price` `pp` ON `pp`.`product_id` = `p`.`product_id`
GROUP BY `p`.`product_id` 
ORDER BY `pp`.`date_updated` DESC

您可能会猜到价格经常变化,我需要拿出最新的。问题是我不知道如何订购 LEFT JOINed 表。我尝试使用一些 GROUP BY 函数,例如 MAX(),但这只会拉出列而不是行。

谢谢。

【问题讨论】:

  • 你能解释一下你希望发生什么吗?您想按组的最大值订购吗?您只想加入最新更新吗?也许一些示例数据和该数据的预期输出将有助于澄清您的问题。
  • 我有一种产品有 5 种不同的价格,它们的 'date_updated' 日期时间不同。我需要加入并提取最新价格。
  • 这是对更大查询的简化。我不能使用 INNER JOIN,因为在实际查询中我加入了许多表并使用 IF 来选择 NOT NULL 列。

标签: mysql


【解决方案1】:

似乎不可能在 GROUP BY 汇总中使用 ORDER BY。我的基本逻辑是有缺陷的。我需要运行以下子查询。

SELECT `p`.*, `pp`.`price` FROM `products` `p` 
LEFT JOIN (
    SELECT `price` FROM `product_price` ORDER BY `date_updated` DESC
) `pp` 
ON `p`.`product_id` = `pp`.`product_id`
GROUP BY `p`.`product_id`;

这会影响性能,但由于它是每一行的相同子查询,所以应该不会太糟糕。

【讨论】:

【解决方案2】:

我认为您需要正确设置别名并设置您要加入的内容:

SELECT p.*, pp.price 
FROM products AS p 
LEFT JOIN product_price AS pp
ON pp.product_id = p.product_id 
GROUP BY p.product_id 
ORDER BY pp.date_updated DESC

【讨论】:

  • 谢谢。我错过了ON部分。我已经编辑了我的查询。我相信 AS 部分是可选的。
【解决方案3】:

这将为您提供最后更新的价格:

select
  p.*, pp.price
from
  products p,
  -- left join this if products may not have an entry in prodcuts_price
  -- and you would like to see a null price with the product
  join 
  (
      select 
        product_price_id, 
        max(date_updated) 
      from products_price
      group by product_price_id
   ) as pp_max
    on p.product_id = pp.product_id
  join products_price pp on 
    pp_max.prodcuts_price_id = pp.products_price_id

【讨论】:

  • 这可能会起作用,但是我真的很想避免做子查询,因为我有一个大数据集。
  • 这就是给出正确结果的方式。其他查询将给出所有个价格。但是,嘿,如果他们工作得更快,那就使用它吧...?@!
  • 感谢您的帮助,但我的查询并没有给出所有价格,它只是给了我一个随机价格,我希望通过正确订购来解决这个问题。
  • @Simon,即使有分析(如果只有 MySQL 支持的话)——你仍然需要一个子查询。
  • 这个输出是什么?如果逻辑/意图明确,(select product_price_id, max(date_updated) from products_price) 将取消投票。看起来像错误的答案
【解决方案4】:

mysql主义:

SELECT p.*, MAX(pp.date_updated), pp.price 
FROM products p 
LEFT JOIN product_price pp ON pp.product_id = p.product_id
GROUP BY p.product_id 

将在一些 RDBMS 上工作:

SELECT p.*, pp.date_updated, pp.price 
FROM products p 
LEFT JOIN product_price pp ON pp.product_id = p.product_id
WHERE (p.product_id, pp.date_updated) 

   in (select product_id, max(date_updated) 
       from product_price 
       group by product_id)

适用于大多数 RDBMS:

SELECT p.*, pp.date_updated, pp.price 
FROM products p 
LEFT JOIN product_price pp ON pp.product_id = p.product_id

WHERE EXISTS
(
    select null -- inspired by Linq-to-SQL style :-)
    from product_price 

    WHERE product_id = p.product_id 

    group by product_id

    HAVING max(date_updated) = pp.date_updated
)

适用于所有 RDBMS:

SELECT p.*, pp.date_updated, pp.price 
FROM products p 
LEFT JOIN product_price pp ON pp.product_id = p.product_id

LEFT JOIN 
(
    select product_id, max(date_updated) as recent 
    from product_price 
    group by product_id
) AS latest 
ON latest.product_id = p.product_id AND latest.recent = pp.date_updated

如果 nate c 的代码意图是从 product_price 中获取一行,则无需 table-derive(即join (select product_price_id, max(date_updated) from products_price) as pp_max),他可能会只需简化(即无需使用 product_price_id 代理主键),如下所示:

SELECT p.*, pp.date_updated, pp.price 
FROM products p 
LEFT JOIN product_price pp ON pp.product_id = p.product_id
WHERE pp.date_updated = (select max(date_updated) from product_price)

【讨论】:

  • 你的 mysqlism 不工作。这就是这篇文章的全部意义所在。选择的价格不是必须,尽管它可能会选择与最大日期一​​致的价格。 dev.mysql.com/doc/refman/5.5/en/group-by-hidden-columns.html
  • 最后一个查询与我的意图无关。
  • 这就是重点,你的子查询中缺少 GROUP BY 子句;所以自然它只会拾取一排。然后你在你的子查询上添加一个 GROUP BY,使用 product_price_id;我可以冒险猜测 product_price_id 是代理主键,而且,它是一个顺序 id,whatdyathink?为什么对一张表的每一行都使用 GROUP BY ?这太荒谬了。关于 Mysqlism,我不确定我的答案,我的盒子上没有 MySQL,我认为 MySQL GROUP BY 具有超能力,我认为它具有 Postgresql 的 DISTINCT ON 功能,你的第一个答案让我想到了:-/
  • 也许你应该把 MySQL 放在你的盒子上,而不是仅仅为 MySQL 问题编造答案!
  • 我以前了解 MySQL,并且我了解许多(正确的)MySQLism。还有你在没有其他字段的情况下对 GROUP BY 的引用,我非常了解,事实上,Postgresql 正在接受它,但有点扭曲,Postgresql 以一种受控方式(Postgres 仍然有纪律)depesz.com/index.php/2010/08/08/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-31
相关资源
最近更新 更多