【问题标题】:Order by and limit on a multiple left join - PostgresSQL and python多个左连接的排序和限制 - PostgresQL 和 python
【发布时间】:2018-04-13 12:31:59
【问题描述】:

我有以下关系:

  • 一个产品有多个图片
  • 一个产品可以有多个类别
  • 一个类别可以有多个产品

我想得到:

  • 只有第一个类别中的“short_name”
  • 只有第一张图片url order_by另一个参数

我在 PostgreSql 中有以下 SQL:

SELECT DISTINCT ON(I.product_id) P.id, P.name, P.short_description,
       CAT.short_name AS category, I.url
FROM products_product AS P
LEFT JOIN products_product_categories AS RPC ON P.id = RPC.product_id
LEFT JOIN categories_category AS CAT ON RPC.category_id = CAT.id
LEFT JOIN products_productimage AS I ON I.product_id = P.id
WHERE (P.is_active = TRUE)

我的问题是我不知道限制left join和order by,我尝试添加LIMIT 1

LEFT JOIN categories_category AS CAT ON RPC.category_id = CAT.id LIMIT 1

但它不起作用,我收到代码错误'syntax error at or near "LEFT"'

分类表

id | category_name | category_short_name
 1    catA                  A
 2    catB                  B
 3    catC                  C

产品表

id | product_name | product_desc
 1    P1                  lorem1
 2    P2                  lorem2
 3    P3                  lorem3

多对多:product_category

id  product_id category_id
1    1          1
2    2          1   
3    1          2
4    3          3   
5    3          3

图像表

id url product_id order
1  lo1    1       4 
2  lo2    1       0 
3  lo3    1       1
4  lo4    2       0

对于 id1 的产品,我希望得到:

name: P1, desc 'lorem1', category short_name : cat A, image url lo2 

【问题讨论】:

  • 添加一些示例表数据和预期结果。 (格式化文本,而不是图像。)在花费太多时间之前考虑阅读stackoverflow.com/help/mcve
  • @jarlh 我用示例更新了代码

标签: sql postgresql


【解决方案1】:

DISTINCT ON 没有ORDER BY 就毫无意义。由于您需要两个不同的订单(i.order 用于图像,cat.id 用于类别),因此您必须在单独的子查询中执行此操作。

select p.id, p.name, p.short_description, c.short_name, i.url
from products_product p
left join
(
  select distinct on (pcat.product_id) pcat.product_id, cat.short_name
  from products_product_categories pcat
  join categories_category cat on cat.id = pcat.category_id
  order by pcat.product_id, cat.id
) c on c.product_id = p.id
left join
(
  select distinct on (product_id) product_id, url
  from products_productimage
  order by product_id, order
) i on i.product_id = p.id
where p.is_active
order by p.id;

编写此查询的两种替代方法是:

  • 仅在 select 子句中获取第一行的子查询
  • 仅获取第一行的子查询的横向左连接

【讨论】:

  • 我使用 distinct on 作为 Limit 1 替换,因为我只想要第一个元素
  • 是的,但是DISTINCT ON 在一个组中工作,在你的情况下是product_id。所以你得到每个product_id 的第一行。现在您必须定义“第一行”是什么。您可以使用ORDER BY 执行此操作。您的查询不包含ORDER BY,因此DISTINCT ON 毫无意义(我很惊讶它甚至不会导致语法错误)。
猜你喜欢
  • 2020-08-14
  • 2012-09-28
  • 2017-07-01
  • 1970-01-01
  • 2011-03-04
  • 1970-01-01
  • 1970-01-01
  • 2018-10-15
  • 2016-01-26
相关资源
最近更新 更多