获取一列中的值更改后的所有记录

时间:2017-10-31 03:15:49

标签: tsql

我有一张表格可以跟踪用户的姓名,他们所属的群组,他们正在处理的作业以及他们获得该作业的日期:

enter image description here

如果用户只被赋予作业1,那么他们就在A组,我需要检索他们的所有记录。

如果某个用户被赋予了作业2,那么他们就在B组中,我需要从他们第一次获得作业2时检索所有记录,包括:

enter image description here

所以用户1,2和3很容易 - 我需要他们所有的记录。

但是用户4是挑战。我需要第11行的用户4的所有记录,当他们第一次给第2行时,到第13行。看起来这对我来说应该很容易,但我无法弄明白。< / p>

如何编写一个获取MAX(日期)值的查询,该列出现在一列中,按另一列(在本例中为User Name)分组,并为该用户选择包含MAX的所有记录(日期) )以及随后的所有日期?

我试过这种方法:

SELECT *
FROM Table1 t1
WHERE ExecutedDate >= (SELECT MIN(t2.ExecutedDate)
                   FROM Table1 t2
                   WHERE t1.UserName = t2.UserName
                   AND t2.Group = 'A'
                   OR (t2.Group = 'B' AND t2.Assignment = 'Assignment 2'
                   GROUP BY t2.UserName
                   )
AND t1.Group = 'A'
OR (t1.Group = 'B' AND t1.Assignment = 'Assignment 2')

但是我得到的错误是子查询返回了多个值,这在使用=,&gt;,&lt;,&gt; =,=&lt;时是不允许的,或者子查询用作表达式。

我理解错误消息,虽然我无法弄清楚我的子查询如何返回多个值。如果有人可以向我解释,那也会有所帮助。

1 个答案:

答案 0 :(得分:0)

你可以试试这个:

WITH DataSource AS
(
    SELECT UserName
          ,MIN(CASE WHEN [Group] = 'A' THEN 1 ELSE 0 END) AS [HasOnlyAGroup]
          ,MIN(CASE WHEN [Group] = 'B' THEN 1 ELSE 0 END) AS [HasOnlyBGroup]
          ,MIN(CASE WHEN [Group] = 'B' THEN [ExecutedDate] ELSE NULL END) AS [FirstExecutionInBGroup]
    FROM Table1 
    GROUP BY UserName
)
SELECT *
FROM DataSource DS
OUTER APPLY
(
    -- for users, that has assigments from each group, we need to get the ID of the first assigment of group B
    SELECT TOP 1 [Row]
    FROM Table1 TMin
    WHERE DS.[UserName]  = Tmin.[UserName]
        AND DS.[FirstExecutionInBGroup] = Tmin.[ExecutedDate]
        AND DS.[HasOnlyAGroup] = 0 
        AND DS.[HasOnlyBGroup] = 0
    ORDER BY Tmin.[ExecutedDate] ASC
) MinID
INNER JOIN Table1 T1
    ON DS.[UserName] = T1.[UserName]
    AND
    (
        -- case 1: user has only A group assigments - show all rows
        (
            DS.[HasOnlyAGroup] = 1 AND DS.[HasOnlyBGroup] = 0
        )
        -- case 2: user has only B group assigments - retrieve rows from the first time that they were given assignment 2
        OR 
        (
            DS.[HasOnlyAGroup] = 0 AND DS.[HasOnlyBGroup] = 1
            AND
            DS.[FirstExecutionInBGroup] <= T1.[ExecutedDate]
        )
        -- case 3:
        OR
        (
            MinID.[RowID] <= T1.[RowID]
        )

    );

查询可能需要进行一些更改,但我们的想法是使用CTE来检查用户是否只有A或B组分配(或两者)。我们也是他们B分配的第一个日期。然后在OUTER APPLY中,我们使用[Row]日期值获得最小[FirstExecutionInBGroup]值。之后,我们拥有执行业务逻辑所需的所有值。