【发布时间】:2017-01-27 14:54:04
【问题描述】:
我有一个查询返回我想要的结果,但它运行了很长时间。有谁知道更好的写法吗?
我需要每组 Prgno/Prgdate 一行。 首先,我需要通过选择最近的记录来确定每个员工的状态。 然后,如果有任何员工活跃,则整个团队都活跃。
仅选择“A”记录是不够的,因为特定员工的非活动记录可能比活动记录更新。
这是查询:
SELECT X_Prgno,X_Prgdate,X_Status
FROM (
-- sq2 choose the 1st record when ordering by status, this will choose Active before Inactive
SELECT X_Prgno,X_Prgdate,X_Status,
ROW_NUMBER() OVER (PARTITION BY X_Prgno,X_Prgdate ORDER BY X_Status) AS rn
FROM (
-- sq1 choose the most recently updated record per empno, prgno, prgdate
SELECT X_Empno,X_Prgno,X_Prgdate,X_Status,
X_Upddate AS Updated_datetime,
MAX(X_Upddate) OVER (PARTITION BY X_Empno,X_Prgno,X_Prgdate) AS Max_Updated_datetime
FROM X_demo
) sq1
WHERE Updated_datetime = Max_Updated_datetime) sq2
WHERE rn = 1
我首先选择了按 3 列(prgno、prgdate、员工)分组的最新记录。然后先选择活动记录,如果存在活动记录,仅按 2 列分组(prgno,prgdate)。
示例:(希望对您有所帮助,您可以在此示例集上运行上述查询)
create table X_demo(
X_Prgno char(6),
X_Prgdate char(8),
X_Empno int,
X_Status char(1),
X_Upddate datetime);
insert into X_demo values ('P43','20170124',1033,'A','2015-07-06 23:05:32.000');
insert into X_demo values ('P43','20170124',1033,'I','2015-07-06 23:05:07.000');
insert into X_demo values ('P43','20170124',1033,'I','2015-07-06 23:03:58.000');
insert into X_demo values ('P43','20170124',1034,'A','2015-06-03 09:29:46.000');
insert into X_demo values ('P43','20170124',1029,'I','2015-06-03 07:26:36.000');
insert into X_demo values ('P43','20170124',1033,'I','2015-06-02 14:52:53.000');
insert into X_demo values ('P43','20170124',1010,'I','2015-06-02 14:52:12.000');
insert into X_demo values ('P43','20170124',1029,'I','2015-08-29 13:27:35.000');
insert into X_demo values ('P43','20170124',1074,'I','2015-05-19 01:20:06.000');
如果我们按 Prgno、Prgdate 和 Empno 分组,我们应该返回 6 行,每个员工的最新数据。 然后通过 Prgno 和 Prgdate 重新组合以返回该组的“A”。
想要的结果:
X_Prgno X_Prgdate X_Status
P43 20170124 A
感谢您的帮助。
如果我插入另外 2 条记录,两条 Active 员工记录的更多当前记录使它们处于非活动状态,则该组的结果应该是非活动的。
insert into X_demo values ('P43','20170124',1033,'I','2017-01-27 09:30:00.000');
insert into X_demo values ('P43','20170124',1034,'I','2017-01-27 09:30:00.000');
结果:
X_Prgno X_Prgdate X_Status
P43 20170124 I
更新 - 2017-01-30
我将子查询的 MAX OVER PARTITION 部分更改为使用 ROW_NUMBER 函数。 它将查询运行时间缩短了几秒钟,但仍然运行时间过长。
SELECT X_Prgno,X_Prgdate,X_Status
FROM (
-- sq2 choose the 1st record when ordering by status, this will choose Active before Inactive
SELECT X_Prgno,X_Prgdate,X_Status,
ROW_NUMBER() OVER (PARTITION BY X_Prgno,X_Prgdate ORDER BY X_Status) AS sq2_rn
FROM (
-- sq1 choose the most recently updated record per prgno, prgdate, empno
SELECT X_Prgno,X_Prgdate,X_Empno,X_Status,X_upddate,
ROW_NUMBER() OVER (PARTITION BY X_Prgno,X_Prgdate,X_Empno
ORDER BY X_Upddate DESC,X_Status) AS sq1_rn
FROM X_demo) sq1
WHERE sq1_rn = 1) sq2
WHERE sq2_rn = 1
【问题讨论】:
-
感谢您的帮助。
-
那么您是否只需要每个组的最新活动记录(如果存在)?
-
请发布您想要的结果。
-
期望的结果是一行。我把它包括在上面了。
标签: sql sql-server