无法在语句中的select中使用子查询

时间:2014-04-23 22:30:30

标签: sql sql-server

手头的问题是无法在select语句中使用具有以下所需输出的子查询:

ActivityName参加进行中取消已注册

 - ProdA     8           3      1         2

 - ProdB    16           5      3         4

以下是我当前代码的示例。有没有办法不使用子查询?

select  
    (select act.ActivityName
        from [dbo].[dimActivity] act
        WHERE act.Code in ('SJM-GTD-HMM-A01')
    ) ActivityName,
    (Select count( emp.ID) 
        FROM [dbo].[factAttempt] fact
        INNER JOIN [dbo].[dimActivity] act ON act.ID = fact.ActivityID
        INNER JOIN [dbo].[dimUser] emp ON emp.ID = fact.UserID
        INNER JOIN [dbo].[dimDate] dt ON fact.EndDtID = dt.DateID
        INNER JOIN [dbo].[dimCompletionStatus] comp ON fact.CompletionStatusID = comp.ID
        INNER JOIN [dbo].[dimAttendanceStatus] att ON fact.AttendanceStatusID = att.ID

        WHERE (act.Code in ('SJM-GTD-HMM-A01','SJM-GTD-HMM-MAN01','SJM-GTD-HMM-PRT01','SJM-GTD-HMM-LAS01'))
        and att.name like ('%Attend%') 
    ) Attended,
    (Select count( emp.ID) 
        FROM [dbo].[factAttempt] fact
        INNER JOIN [dbo].[dimActivity] act ON act.ID = fact.ActivityID
        INNER JOIN [dbo].[dimUser] emp ON emp.ID = fact.UserID
        INNER JOIN [dbo].[dimDate] dt ON fact.EndDtID = dt.DateID
        INNER JOIN [dbo].[dimCompletionStatus] comp ON fact.CompletionStatusID = comp.ID
        INNER JOIN [dbo].[dimAttendanceStatus] att ON fact.AttendanceStatusID = att.ID

        WHERE (act.Code in ('SJM-GTD-HMM-A01','SJM-GTD-HMM-MAN01','SJM-GTD-HMM-PRT01','SJM-GTD-HMM-LAS01'))
        and att.name like ('%Progress%') 
    ) Inprogess,
        (Select count( emp.ID) 
        FROM [dbo].[factAttempt] fact
        INNER JOIN [dbo].[dimActivity] act ON act.ID = fact.ActivityID
        INNER JOIN [dbo].[dimUser] emp ON emp.ID = fact.UserID
        INNER JOIN [dbo].[dimDate] dt ON fact.EndDtID = dt.DateID
        INNER JOIN [dbo].[dimCompletionStatus] comp ON fact.CompletionStatusID = comp.ID
        INNER JOIN [dbo].[dimAttendanceStatus] att ON fact.AttendanceStatusID = att.ID

        WHERE (act.Code in ('SJM-GTD-HMM-A01','SJM-GTD-HMM-MAN01','SJM-GTD-HMM-PRT01','SJM-GTD-HMM-LAS01'))
        and att.name like ('%Cancel%') 
    ) Cancelled,
    (Select count( emp.ID) 
        FROM [dbo].[factAttempt] fact
        INNER JOIN [dbo].[dimActivity] act ON act.ID = fact.ActivityID
        INNER JOIN [dbo].[dimUser] emp ON emp.ID = fact.UserID
        INNER JOIN [dbo].[dimDate] dt ON fact.EndDtID = dt.DateID
        INNER JOIN [dbo].[dimCompletionStatus] comp ON fact.CompletionStatusID = comp.ID
        INNER JOIN [dbo].[dimAttendanceStatus] att ON fact.AttendanceStatusID = att.ID

        WHERE (act.Code in ('SJM-GTD-HMM-A01','SJM-GTD-HMM-MAN01','SJM-GTD-HMM-PRT01','SJM-GTD-HMM-LAS01'))
        and att.name like ('%NA%') 
    ) Registered

1 个答案:

答案 0 :(得分:2)

主要选择'ActivityName'应该是主查询,每个子查询都嵌套在里面,格式为:

SELECT act.ActivityName, {otherSubqueriesGoHere} 
FROM [dbo].[dimActivity] act 
WHERE act.Code in ('SJM-GTD-HMM-A01')

然后,在子查询中,您可以引用主结果集中的值,以便将子查询结果过滤为仅当前行的活动。

以下是修改后的查询示例。您需要更改每个子查询中的and act.ID = actMain.ID部分,以使用dimActivity表的主键而不是ID。我刚刚使用ID,因为我不知道你的表结构是什么。

SELECT  
    actMain.ActivityName,
    (   Select count( emp.ID) 
        FROM [dbo].[factAttempt] fact
        INNER JOIN [dbo].[dimActivity] act ON act.ID = fact.ActivityID
        INNER JOIN [dbo].[dimUser] emp ON emp.ID = fact.UserID
        INNER JOIN [dbo].[dimDate] dt ON fact.EndDtID = dt.DateID
        INNER JOIN [dbo].[dimCompletionStatus] comp ON fact.CompletionStatusID = comp.ID
        INNER JOIN [dbo].[dimAttendanceStatus] att ON fact.AttendanceStatusID = att.ID

        WHERE (act.Code in ('SJM-GTD-HMM-A01','SJM-GTD-HMM-MAN01','SJM-GTD-HMM-PRT01','SJM-GTD-HMM-LAS01'))
        and att.name like ('%Attend%') 
        and act.ID = actMain.ID

    ) Attended,
    (   Select count( emp.ID) 
        FROM [dbo].[factAttempt] fact
        INNER JOIN [dbo].[dimActivity] act ON act.ID = fact.ActivityID
        INNER JOIN [dbo].[dimUser] emp ON emp.ID = fact.UserID
        INNER JOIN [dbo].[dimDate] dt ON fact.EndDtID = dt.DateID
        INNER JOIN [dbo].[dimCompletionStatus] comp ON fact.CompletionStatusID = comp.ID
        INNER JOIN [dbo].[dimAttendanceStatus] att ON fact.AttendanceStatusID = att.ID

        WHERE (act.Code in ('SJM-GTD-HMM-A01','SJM-GTD-HMM-MAN01','SJM-GTD-HMM-PRT01','SJM-GTD-HMM-LAS01'))
        and att.name like ('%Progress%') 
        and act.ID = actMain.ID
    ) Inprogess,
    (   Select count( emp.ID) 
        FROM [dbo].[factAttempt] fact
        INNER JOIN [dbo].[dimActivity] act ON act.ID = fact.ActivityID
        INNER JOIN [dbo].[dimUser] emp ON emp.ID = fact.UserID
        INNER JOIN [dbo].[dimDate] dt ON fact.EndDtID = dt.DateID
        INNER JOIN [dbo].[dimCompletionStatus] comp ON fact.CompletionStatusID = comp.ID
        INNER JOIN [dbo].[dimAttendanceStatus] att ON fact.AttendanceStatusID = att.ID

        WHERE (act.Code in ('SJM-GTD-HMM-A01','SJM-GTD-HMM-MAN01','SJM-GTD-HMM-PRT01','SJM-GTD-HMM-LAS01'))
        and att.name like ('%Cancel%') 
        and act.ID = actMain.ID
    ) Cancelled,
    (   Select count( emp.ID) 
        FROM [dbo].[factAttempt] fact
        INNER JOIN [dbo].[dimActivity] act ON act.ID = fact.ActivityID
        INNER JOIN [dbo].[dimUser] emp ON emp.ID = fact.UserID
        INNER JOIN [dbo].[dimDate] dt ON fact.EndDtID = dt.DateID
        INNER JOIN [dbo].[dimCompletionStatus] comp ON fact.CompletionStatusID = comp.ID
        INNER JOIN [dbo].[dimAttendanceStatus] att ON fact.AttendanceStatusID = att.ID

        WHERE (act.Code in ('SJM-GTD-HMM-A01','SJM-GTD-HMM-MAN01','SJM-GTD-HMM-PRT01','SJM-GTD-HMM-LAS01'))
        and att.name like ('%NA%') 
        and act.ID = actMain.ID
    ) Registered
FROM [dbo].[dimActivity] actMain
WHERE actMain.Code in ('SJM-GTD-HMM-A01')

修改 我只是注意到你的每个子查询基本上都是重复的,只有att.name更改的比较,所以你也可以使用这样的查询,其中包括group by和sum来计算每个查询的出现次数{ {1}}值。

att.name

注意:此查询不包括对所有4个桶(出席,进行,取消,已注册)具有0计数的SELECT act.ActivityName , SUM(case when att.name like ('%Attend%') then 1 else 0 end) as Attended , SUM(case when att.name like ('%Progress%') then 1 else 0 end) as Inprogess , SUM(case when att.name like ('%Cancel%') then 1 else 0 end) as Cancelled , SUM(case when att.name like ('%NA%') then 1 else 0 end) as Registered FROM [dbo].[factAttempt] fact INNER JOIN [dbo].[dimActivity] act ON act.ID = fact.ActivityID INNER JOIN [dbo].[dimUser] emp ON emp.ID = fact.UserID INNER JOIN [dbo].[dimDate] dt ON fact.EndDtID = dt.DateID INNER JOIN [dbo].[dimCompletionStatus] comp ON fact.CompletionStatusID = comp.ID INNER JOIN [dbo].[dimAttendanceStatus] att ON fact.AttendanceStatusID = att.ID WHERE (act.Code in ('SJM-GTD-HMM-A01','SJM-GTD-HMM-MAN01','SJM-GTD-HMM-PRT01','SJM-GTD-HMM-LAS01')) GROUP BY act.ActivityName 。如果您需要包含全0的记录,那么您可以将联接更改为ActivityName,如下所示:

LEFT JOIN