Sql 限制联接中每个组的行数(不限于1行)
鉴于这些表格:Sql 限制联接中每个组的行数(不限于1行),sql,postgresql,join,greatest-n-per-group,sql-limit,Sql,Postgresql,Join,Greatest N Per Group,Sql Limit,鉴于这些表格: TABLE Stores ( store_id INT, store_name VARCHAR, etc ); TABLE Employees ( employee_id INT, store_id INT, employee_name VARCHAR, currently_employed BOOLEAN, etc ); 我想列出每家商店雇佣时间最长的15名员工,比如说15名员工id最低的员工,或者如果有15名员工目前正在工作,那么列出一家商店的所有员工。我
TABLE Stores (
store_id INT,
store_name VARCHAR,
etc
);
TABLE Employees (
employee_id INT,
store_id INT,
employee_name VARCHAR,
currently_employed BOOLEAN,
etc
);
我想列出每家商店雇佣时间最长的15名员工,比如说15名员工id最低的员工,或者如果有15名员工目前正在工作,那么列出一家商店的所有员工。我想用join子句来完成它
我发现很多人只在一行中这样做的例子,通常是一个最小或最大的单个最长雇佣员工,但我想基本上结合ORDER BY和联接内部的限制。以下是其中一些例子:
我还找到了一个很好的例子,可以一家一家地做这件事。我没有,我有大约5000家店铺:
我还看到,您可以使用TOP而不是orderby和LIMIT,但PostgreSQL不能
我认为这两个表之间的join子句并不是实现这一点的唯一方法,甚至不一定是最好的方法,如果可以只在employees表中使用不同的store_id,那么我愿意接受其他方法。以后可以随时加入
由于我对SQL非常陌生,我希望有任何理论背景或其他解释可以帮助我理解工作原理。一种经典的方法是使用A,例如排名: 获取每组前n行的一般解决方案是使用窗口函数row_number: 完美的索引应该是这样的部分多列索引:
CREATE INDEX ON employees (store_id, employee_id) WHERE currently_employed
细节取决于问题中缺少的细节。相关示例:
这两个版本都不包括没有当前员工的商店。如果你需要的话,有很多方法可以解决这个问题
SELECT *
FROM (
SELECT *, row_number() OVER (PARTITION BY store_id ORDER BY employee_id) AS rn
FROM employees
WHERE currently_employed
) e
JOIN stores s USING (store_id)
WHERE rn <= 15
ORDER BY store_id, e.rn;
SELECT s.store_name, e.*
FROM stores s
, LATERAL (
SELECT * -- or just needed columns
FROM employees
WHERE store_id = s.store_id
AND currently_employed
ORDER BY employee_id
LIMIT 15
) e
-- WHERE ... possibly select only a few stores
ORDER BY s.store_name, e.store_id, e.employee_id
CREATE INDEX ON employees (store_id, employee_id) WHERE currently_employed