SQL查询仅根据流体条件返回一行

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与数据一起带回:

  • 10:该客户没有得到恢复,因为客户从之前的4/1截止日期的员工删除.
  • 11:这位客户DOES得到恢复,因为员工已经有客户过去的5/31截止日期,即使没有审查客户
  • 15:这位客户DOES得到恢复,因为它是从他们删除前的职员有顾客过去的4/1截止日期.
  • 17:从2018年6月29日的客户参与DOES得到恢复,但是从2018年6月13日的客户的参与也不要得到恢复,因为它发生前的审查与该客户(实际上当一个客户雇员开始日期是做过去5月31日活动仅在他们与该客户进行审核之后才计算 - 在此审核日期之前发生的所有活动都会被忽略)
  • 19:客户参与DOES在这种情况下得到恢复,因为员工是6/1之前分配给他们,所以不管了审查,优先于其他项目发生做的任何活动计数.

希望这种解释和分解是有道理的.

更新:这是表脚本和预期结果:

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)

预期成绩:

在此输入图像描述

Ang*_* M. 5

我不确定我是否理解你的所有要求.事实上,我遗漏了一些东西,因为我得到的结果并不完全相同.我准备的代码:

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%明确,因为它们基于现实生活中常见的例子.有必要清楚地确定必须应用的业务规则以及需要应用的顺序(顺序).所以,根据我的猜测,我已经构建了以下解决方案.这个解决方案的优点是它很容易调试:

  1. 每个规则都标有一个可以在调试模式下显示的数字(如果之后需要,则会被忽略),并告诉我们应用了哪个规则
  2. 这些规则是按顺序应用的,因此,如果一条规则要显示记录,则不会应用其余规则.这是因为检查规则的顺序很重要
  3. 规则的负数表示该规则表示不应显示记录.

:

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)

此方法的最佳方法是计算并显示已应用的规则,因此,当查询显示已应用的规则时,可以非常轻松地对其进行调试.如果规则的顺序或某些规则不正确,则可以非常快速地检测并修复它.这同样适用于未来的更改,因为通常这些基于日期的规则经常发生变化,我们需要一种简单的方法来维护代码.最后,我希望这个练习能为未来的发展提供一些想法,因为在创建代码时可追溯性和可支持性非常重要.