仅返回唯一值

时间:2016-08-26 18:05:59

标签: sql sql-server sql-server-2008

我试图计算完成了多少工作,无论工作人员是谁。我需要做的是过滤掉任何重复项,但问题是整行不重复,所以DISTINCT在这里工作不了。我想过滤掉基于JobCode,JobType TaskTime和星期几的重复。所以我的表格如下:

JobCode JobType TaskTime    EmployeeID  M   Tu  W   Th  F   Sa  Su
==================================================================
1800    1       06:49       101         1   1   1   1   1   0   0
1800    1       06:49       102         1   0   0   0   0   0   0
1800    1       07:04       101         1   1   1   1   1   0   0
1800    1       07:26       101         1   1   1   1   1   0   0
1800    1       07:49       101         1   1   1   1   1   0   0
1800    2       15:55       101         1   1   1   1   1   0   0
1800    1       16:20       101         1   1   1   1   1   0   0
1800    1       16:50       101         1   1   1   1   1   0   0
1800    2       16:55       101         1   1   1   1   1   0   0

我的SQL查询就像这样

SELECT t1.JobCode, t1.JobType,  
    t1.M, t1.Tu, t1.W, t1.Th, t1.F, t1.Sa, t1.Su,
    SUM(t1.M + t1.Tu + t1.W + t1.Th + t1.F + t1.Sa + t1.Su) as Totals
FROM Table1 AS t1
JOIN Table1 AS t1_overlap ON
    t1_overlap.EmployeeID = t1.EmployeeID AND
    t1_overlap.JobType = t1.JobType AND
    t1_overlap.TaskTime = t1.TaskTime
    AND 
    (
    (t1.M = 1 AND t1_overlap.M = t1.M) OR
    (t1.Tu = 1 AND t1_overlap.Tu = t1.Tu) OR
    (t1.W = 1 AND t1_overlap.W = t1.W) OR
    (t1.Th = 1 AND t1_overlap.Th = t1.Th) OR
    (t1.F = 1 AND t1_overlap.F = t1.F) OR
    (t1.Sa = 1 AND t1_overlap.Sa = t1.Sa) OR
    (t1.Su = 1 AND t1_overlap.Su = t1.Su)
    )
GROUP BY t1.JobCode, t1.JobType, t1.M, t1.Tu, t1.W, t1.Th, t1.F, t1.Sa, t1.Su

返回的数据是这样的

JobCode JobType M   Tu  W   Th  F   Sa  Su  Totals
==================================================
1800    1       1   0   0   0   0   0   0   1
1800    1       1   1   1   1   1   0   0   30
1800    2       1   1   1   1   1   1   1   10

我想看到的只是唯一的价值观,所以我不希望第一行显示员工102只在M上工作,因为我已经看到员工101工作了在同一天和那个时间做同样的工作。所以我想看的是以下内容:

JobCode JobType M   Tu  W   Th  F   Sa  Su  Totals
==================================================
1800    1       1   1   1   1   1   0   0   30
1800    2       1   1   1   1   1   0   0   10

我真的不需要看一周中的日子,我只是在这里展示它们,所以我可以看到什么回来了。实际上我需要查看输出的是JobCode,JobType和Totals,如下所示:

JobCode JobType Totals
======================
1800    1       30
1800    2       10

非常感谢帮助。

3 个答案:

答案 0 :(得分:2)

我认为一个快速的子查询,你抓住每一天的最大值,按你的键分组,然后总结结果,就可以了:

SELECT
    jobcode,
    jobtype,
    sum(monday+tuesday+wednesday+thursday+friday+saturday+sunday) AS total
FROM
    (
        SELECT
            jobcode,
            jobtype,
            tasktime,
            max(m) as monday,
            max(tu) as tuesday,
            max(w) as wednesday,
            max(th) as thursday,
            max(f) as friday,
            max(sa) as saturday,
            max(su) as sunday
        FROM Table1 T1
        GROUP BY jobcode, jobtype, tasktime
    ) t2
GROUP BY jobcode, jobtype

可能有一些比这更有说服力的东西,但这应该可以完成工作。

答案 1 :(得分:0)

尝试使用以下查询。

;With cte1
as
(SELECT ROW_NUMBER()OVER(PArtition by t1.JobCode,t1.JobType order by t1.JobCode,t1.JobType) RNO,t1.JobCode, t1.JobType,
    SUM(t1.M + t1.Tu + t1.W + t1.Th + t1.F + t1.Sa + t1.Su) OVER(partition by t1.JobCode,t1.JobType ORDER BY t1.JobCode,t1.JobType ) as Totals
FROM Table1 AS t1
JOIN Table1 AS t1_overlap ON
    t1_overlap.EmployeeID = t1.EmployeeID AND
    t1_overlap.JobType = t1.JobType AND
    t1_overlap.TaskTime = t1.TaskTime
    AND 
    (
    (t1.M = 1 AND t1_overlap.M = t1.M) OR
    (t1.Tu = 1 AND t1_overlap.Tu = t1.Tu) OR
    (t1.W = 1 AND t1_overlap.W = t1.W) OR
    (t1.Th = 1 AND t1_overlap.Th = t1.Th) OR
    (t1.F = 1 AND t1_overlap.F = t1.F) OR
    (t1.Sa = 1 AND t1_overlap.Sa = t1.Sa) OR
    (t1.Su = 1 AND t1_overlap.Su = t1.Su)
    ))

    SELECT t1.JobCode, t1.JobType,Totals
    FROM cte1
    WHERE RNO=1

答案 2 :(得分:0)

基本上,您可以使用超级棒ROW_NUMBER函数并包装查询,以便您有效地1)定义分组,以及2)仅占用每个组的第一行。仔细查看over (partition by ... order by ...)子句,了解如何控制分组和“排名”(您想要通过哪些结果)。

select JobCode, JobType, Totals
from (
    SELECT t1.JobCode, t1.JobType, SUM(t1.M + t1.Tu + t1.W + t1.Th + t1.F + t1.Sa + t1.Su) as Totals
           ,row_number() over (partition by t1.JobCode order by t1.JobType) as rseq
    FROM Table1 AS t1
    JOIN Table1 AS t1_overlap ON
        t1_overlap.EmployeeID = t1.EmployeeID AND
        t1_overlap.JobType = t1.JobType AND
        t1_overlap.TaskTime = t1.TaskTime
        AND 
        (
        (t1.M = 1 AND t1_overlap.M = t1.M) OR
        (t1.Tu = 1 AND t1_overlap.Tu = t1.Tu) OR
        (t1.W = 1 AND t1_overlap.W = t1.W) OR
        (t1.Th = 1 AND t1_overlap.Th = t1.Th) OR
        (t1.F = 1 AND t1_overlap.F = t1.F) OR
        (t1.Sa = 1 AND t1_overlap.Sa = t1.Sa) OR
        (t1.Su = 1 AND t1_overlap.Su = t1.Su)
        )
    GROUP BY t1.JobCode, t1.JobType, t1.M, t1.Tu, t1.W, t1.Th, t1.F, t1.Sa, t1.Su
) x
where rseq = 1 --filter to keep only the "first" row (JobType) for each JobCode

请注意,有关“您如何决定保留哪一个”的注释是有效的,本示例假设您希望看到“每个JobCode一行”,并保留“该JobCode的第一个JobType”。如果你能更清楚地解释你想要使用的逻辑,可以调整它以适应。