Mat*_*ttE 3 sql-server subquery
我知道这是可能的,但我不确定如何设置它.基本上我需要为每个员工提取数据,但前提是它满足基于几个不同日期的某些标准.
例如,如果员工在6/1之前被分配到公司,则会自动计算.
如果员工在6/1之后被分配到公司,那么只有在他们被分配之后才能对该公司进行审核(即,他们在6月25日被分配并在7/1进行审核时),他们才会被计算在内. .这应该被计算在内.例如,如果他们在6月25日被分配并且审查发生在6月15日,那么他们将不计入这名员工)
如果员工在4/1之前被从公司中移除,他们就不会被计算在内.如果它们在4/1或之后被移除则重要.
因此,关键列是员工 - 客户表中的审核创建日期,开始日期和结束日期.
我认为这需要某种类型的子查询,它返回该客户的员工的开始日期,然后根据评估此日期的Case语句与审核日期比较审核日期,但我不确定如何执行此操作.
任何帮助,将不胜感激.
编辑:表结构/数据如下:
员工 - 客户表
ID EmpID CustID StartDate EndDate
1 4 10 10/1/2017 2/21/2018
2 4 11 10/1/2017 7/31/2018
3 4 15 10/1/2017 4/8/2018
4 4 17 6/1/2018 NULL (means still active with this employee)
5 4 19 5/18/2018 NULL
Run Code Online (Sandbox Code Playgroud)
客户数据表
ID CustID ActivityDate Task
1 10 1/13/2018 Review
3 15 4/2/2018 Review
4 17 6/25/2018 Review
5 17 6/13/2018 Client Engagement
6 17 6/29/2018 Client Engagement
7 19 5/25/2018 Client Engagement
8 19 6/28/2018 Review
Run Code Online (Sandbox Code Playgroud)
因此,对于此示例,我想要一个查询,根据条件将以下客户ID与数据一起带回:
希望这种解释和分解是有道理的.
更新:这是表脚本和预期结果:
CREATE TABLE Cust_Employee(
Cust_Emp_ID int IDENTITY(1,1) NOT NULL,
Cust_ID int NOT NULL,
Emp_ID int NULL,
Start_Date datetime NULL,
End_Date datetime NULL,
CONSTRAINT PK_Cust_Employee PRIMARY KEY CLUSTERED
(
Cust_Emp_ID ASC
)WITH (PAD INEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON PRIMARY
)ON PRIMARY
GO
CREATE TABLE Cust_Data(
Cust_Data_ID int IDENTITY(1,1) NOT NULL,
Cust_ID int NULL,
Activity_Date datetime NULL,
Task VARCHAR(50) NULL
)
CONSTRAINT PK_Client_Data PRIMARY KEY CLUSTERED
(
Cust_Data_ID ASC
)WITH (PAD INEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON PRIMARY
)ON PRIMARY
GO
INSERT INTO Cust_Employee VALUES(4, 10, '10/1/2017', '2/21/2018')
INSERT INTO Cust_Employee VALUES(4, 11, '10/1/2017', '7/31/2018')
INSERT INTO Cust_Employee VALUES(4, 15, '10/1/2017', '4/8/2018')
INSERT INTO Cust_Employee VALUES(4, 17, '6/1/2018', NULL)
INSERT INTO Cust_Employee VALUES(4, 19, '5/18/2018', NULL)
INSERT INTO Cust _Data VALUES(10, '1/13/2018', 'Review')
INSERT INTO Cust _Data VALUES(15, '4/2/2018', 'Review')
INSERT INTO Cust _Data VALUES(17, '6/25/2018', 'Review')
INSERT INTO Cust _Data VALUES(17, '6/13/2018', 'Client Engagement')
INSERT INTO Cust _Data VALUES(17, '6/29/2018', 'Client Engagement')
INSERT INTO Cust _Data VALUES(19, '5/25/2018', 'Client Engagement')
INSERT INTO Cust _Data VALUES(19, '6/28/2018', 'Review')
Run Code Online (Sandbox Code Playgroud)
预期成绩:
我不确定我是否理解你的所有要求.事实上,我遗漏了一些东西,因为我得到的结果并不完全相同.我准备的代码:
SELECT E.Cust_ID AS Emp_ID, E.Emp_ID AS Cust_ID, E.Start_Date, E.End_Date,
MAX(D.Activity_Date) AS Activity_Date, D.Task
FROM Cust_Employee E
LEFT OUTER JOIN Cust_Data D
ON E.Emp_ID = D.Cust_ID
WHERE COALESCE(E.End_Date, GETDATE()) > '20180401'
GROUP BY
E.Cust_ID, E.Emp_ID, E.Start_Date, E.End_Date,
D.Task
ORDER BY E.Cust_ID;[![enter image description here][1]][1]
Run Code Online (Sandbox Code Playgroud)
因此,我的查询显示了Emp 19的额外行,不知道将消除的条件是什么,如果您澄清我自己将更正响应.
首先,我必须认识到对我的要求并非100%明确,因为它们基于现实生活中常见的例子.有必要清楚地确定必须应用的业务规则以及需要应用的顺序(顺序).所以,根据我的猜测,我已经构建了以下解决方案.这个解决方案的优点是它很容易调试:
:
WITH CTE AS (
SELECT E.Cust_ID AS Emp_ID, E.Emp_ID AS Cust_ID,
E.Start_Date, E.End_Date,
MAX(D.Activity_Date) AS Activity_Date, D.Task,
CASE
-- RULE -1: Removed Prior to 4/1 cutoff date
WHEN E.End_Date < '20180401' THEN -1
-- RULE 1: If the employee has had the customer past the 5/31 cutoff date, even though there is no review for the customer
WHEN E.End_Date > '20180531' THEN 1
-- RULE 2: If the employee had the customer past the 4/1 cutoff date before it was removed from them
WHEN D.Activity_Date > '20180401' AND D.Activity_Date <= E.End_Date THEN 2
-- RULE -2: Client engagement from 6/13/2018 does NOT get returned because it happened BEFORE the review was done with this client
WHEN D.Task = 'Client Engagement'
AND NOT EXISTS (SELECT 1 FROM Cust_Data D2 WHERE D2.Cust_ID = E.Emp_ID AND D2.Task = 'Review' AND D2.Activity_Date <= D.Activity_Date)
THEN -2
-- RULE 12: If the employee was assigned to a company before 6/1 they get counted automatically.
WHEN E.Start_Date <= '20180601' THEN 12
-- RULE 14: If EndDate later than June-1-2018
WHEN COALESCE(E.End_Date, GETDATE()) > '20180601' THEN 14
-- RULE 0: Other cases
ELSE 0
END AS [Rule]
FROM Cust_Employee E
LEFT OUTER JOIN Cust_Data D
ON E.Emp_ID = D.Cust_ID
--AND D.Activity_Date > '20180401'
GROUP BY
E.Cust_ID, E.Emp_ID, E.Start_Date, E.End_Date,
D.Task, D.Activity_Date
)
SELECT Emp_ID, Cust_ID, Start_Date, End_Date, Activity_Date, Task, [Rule]
FROM CTE
WHERE [Rule] > 0
ORDER BY Cust_ID, Start_Date, Activity_Date;
Run Code Online (Sandbox Code Playgroud)
此方法的最佳方法是计算并显示已应用的规则,因此,当查询显示已应用的规则时,可以非常轻松地对其进行调试.如果规则的顺序或某些规则不正确,则可以非常快速地检测并修复它.这同样适用于未来的更改,因为通常这些基于日期的规则经常发生变化,我们需要一种简单的方法来维护代码.最后,我希望这个练习能为未来的发展提供一些想法,因为在创建代码时可追溯性和可支持性非常重要.
| 归档时间: |
|
| 查看次数: |
323 次 |
| 最近记录: |