微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

mysql-使用外部联接并限制每个父级的子记录的SQL查询

我在弄清楚如何构造SQL查询时遇到了麻烦.假设我们有一个User表和一个Pet表.每个用户可以拥有许多宠物,并且宠物具有品种栏.

User:

id    |    name
______|________________
1     |    Foo
2     |    Bar

Pet:

id    |    owner_id    |    name    |    breed    |
______|________________|____________|_____________|
1     |        1       |  Fido      |  poodle     |   
2     |        2       |  Fluffy    |  siamese    |

最终目标是提供一个查询,该查询将为我提供与给定where子句匹配的每个用户的所有宠物,同时允许使用sort和limit参数.因此,可以将每个用户的宠物限制为5个并按名称排序.

我正在为ORM动态构建这些查询,因此我需要一个可以在MysqL和Postgresql中运行的解决方案(尽管它可以是两个不同的查询).

我已经尝试过类似的方法,但不起作用:

SELECT "user"."id", "user"."name", "pet"."id", "pet"."owner_id", "pet"."name",
  "pet"."breed"
FROM "user"
LEFT JOIN "pet" ON "user"."id" = "pet"."owner_id"
WHERE "pet"."id" IN
  (SELECT "pet"."id" FROM "pet" WHERE "pet"."breed" = 'poodle' LIMIT 5)

解决方法:

在Postgres(8.4或更高版本)中,在子查询中使用window function row_number()

SELECT user_id, user_name, pet_id, owner_id, pet_name, breed
FROM  (
   SELECT u.id AS user_id, u.name AS user_name
        , p.id AS pet_id, owner_id, p.name AS pet_name, breed
        , row_number() OVER (PARTITION BY u.id ORDER BY p.name, pet_id) AS rn
   FROM  "user"    u
   LEFT   JOIN pet p ON p.owner_id = u.id
                    AND p.breed = 'poodle'
   ) sub
WHERE  rn <= 5
ORDER  BY user_name, user_id, pet_name, pet_id;

>使用左联接时,不能将其与左侧表的WHERE条件结合使用.这会强制将LEFT JOIN转换为普通的[INNER] JOIN(并可能从您不想删除的结果中删除行).将此类条件拉入join子句.
按照我的方式,结果是包括没有宠物的用户-与您的查询存根相反.
> ORDER BY子句中的其他id列应该打破非唯一名称间的可能联系.
>切勿使用reserved word like user作为标识符.
>按照您的命名约定进行工作. id或name是可怕的,非描述性的选择,即使某些ORM提出了这种废话.正如您在查询中看到的那样,当连接几个表时,这会导致复杂化,这是您在sql中所做的.
首先应该是pet_id,pet,user_id,用户名等.
>使用适当的命名约定,我们可以仅在子查询中选择*.

MysqL不支持窗口函数,有烦躁的替代品…

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐