【发布时间】:2015-06-23 13:26:54
【问题描述】:
我有设计师和设计表
设计师有很多设计
我想让所有设计师为每个设计师设计 10 个设计
有没有办法在 postgresql、mysql 中的单个查询中做到这一点
【问题讨论】:
-
查询在哪里?以及哪个数据库?
-
请完善您的问题,添加一些详细信息,例如表结构、您当前的查询等。
标签: mysql sql postgresql
我有设计师和设计表
设计师有很多设计
我想让所有设计师为每个设计师设计 10 个设计
有没有办法在 postgresql、mysql 中的单个查询中做到这一点
【问题讨论】:
标签: mysql sql postgresql
为了在 Postgres 中获得最佳性能(在 MySQL 中不可能),请使用 LATERAL 连接:
SELECT d.designer, d1.design -- whatever columns you need
FROM designer d
LEFT JOIN LATERAL (
SELECT * -- or just needed columns
FROM design
WHERE designer_id = d.designer_id
-- ORDER BY ??? -- you may want to pick certain designs
LIMIT 10
) d1 ON true
ORDER BY d.designer_id, d.design_id; -- or whatever
这为每位设计师提供 10 个设计 - 如果更少,则与他/她拥有的一样多。
LEFT JOIN LATERAL ... ON true 将设计师保留在没有单一设计(目前)的结果中。
如果您添加一个与design 上的现有索引 匹配的ORDER BY 子句,您将获得最佳性能,例如:
CREATE INDEX foo ON design (designer_id, design_id)
然后,在上述查询中的子查询d1:
...
ORDER BY design_id
...
现在 Postgres 可以直接从索引中挑选最上面的项目。
更多细节的相关答案:
【讨论】:
select * from (
Select row_number() OVER (PARTITION BY a.designer ORDER BY b.design DESC) rn,
a.* ,b.*
from a
inner join b
on a.id = b.id
)
where rn <= 10
mysql没有你需要的窗口函数,所以这是postgresql。
【讨论】:
在 MySQL 中,您可以利用用户定义的变量来模拟其他数据库中可用的一些分析函数...
SELECT v.designer_id
, v.design_id
FROM ( SELECT @rn := IF(r.id = @prev_r_id,@rn+1,1) AS rn
, @prev_r_id := r.id AS designer_id
, d.id AS design_id
FROM (SELECT @rn := 0, @prev_r_id := NULL) i
CROSS
JOIN designer r
LEFT
JOIN design d
ON d.designer_id = r.id
ORDER BY r.id, d.id
) v
WHERE v.rn <= 10
ORDER BY v.designer_id, v.design_id
您可以只运行内联视图查询 (v) 来查看返回的内容。它的作用是按designer_id 对行进行排序,并将当前行的值与前一行的值进行比较...如果它们匹配,则将@rn 递增1,否则将@rn 重置为1. 净效果是我们从rn 中得到一个升序整数序列,每个designer_id... 1,2,3。
外部查询过滤掉rn大于10的行。
如果给定的designer 的designs 少于十行,则该designer 的行数少于十行。
【讨论】: