SQL 服务器 - 联合所有

SQL Server - UNION ALL

我是 SQL 开发的新手,我需要对两个 select 语句执行 UNION。下面是一个示例查询。 Join 表和条件,其中条件、列名和所有内容在 select 语句中都是相同的,除了 FROM 子句之后的主表。我只是想知道是否有一种方法可以进行单个静态 select 查询,而不是为 UNION 重复相同的查询两次(无需进行动态查询)。

SELECT Sum(ABC.Intakes) As TotalIntakes, Sum(ABC.ClientTarget) as TotalClientTarget
FROM(

    SELECT Sum(tt.IntakesReceived) As Intakes, Sum(tt.ClientTarget) As ClientTarget, 
        tt.ProgramId 
    FROM 
        (SELECT Count(DISTINCT ClientID) As IntakesReceived,  
           DATEDIFF(MONTH, L.AwardStartDate, L.AwardEndDate)*L.MonthlyClientTarget As ClientTarget, 
           L.AwardId, L.ProgramId
        FROM IntakeCoverageLegacy As L
          LEFT JOIN UserRoleEntity URE ON URE.EntityId  = L.AwardId
          LEFT JOIN CDPUserRole UR ON URE.UserRoleId = UR.Id AND UR.CDPUserId = @UserId     
        WHERE (@Program IS NULL OR L.ProgramId IN (SELECT ProgramID FROM @ProgramIDList)
          AND (ufn_IsInternalUser(@UserId) = 1
               OR (ufn_IsInternalUser(@UserId) = 0 AND UR.CDPUserId = @UserId ))    
        GROUP BY L.AwardId, L.ProgramId) As tt  
    GROUP BY tt.ProgramId, tt.ProgramName             

 UNION ALL

    SELECT Sum(tt.IntakesReceived) As Intakes, Sum(tt.ClientTarget) As ClientTarget, 
        tt.ProgramId 
    FROM 
       (SELECT Count(DISTINCT C.ClientID) As IntakesReceived,  
         DATEDIFF(MONTH, C.AwardStartDate, C.AwardEndDate)*L.MonthlyClientTarget As ClientTarget, 
         C.AwardId, C.ProgramId
       FROM IntakeCoverageCDP As C
          LEFT JOIN UserRoleEntity URE ON URE.EntityId  = L.AwardId
          LEFT JOIN CDPUserRole UR ON URE.UserRoleId = UR.Id AND UR.CDPUserId = @UserId     
       WHERE (@Program IS NULL OR C.ProgramId IN (SELECT ProgramID FROM @ProgramIDList)
           AND (ufn_IsInternalUser(@UserId) = 1
                OR (ufn_IsInternalUser(@UserId) = 0 AND UR.CDPUserId = @UserId ))   
       GROUP BY C.AwardId, C.ProgramId) As tt   
   GROUP BY tt.ProgramId, tt.ProgramName

) As ABC
GROUP BY ABC.ProgramId

好的...我之前发布的是示例查询,我已将示例更新为我的实际查询以使其更加清晰。只是主表不同。我的要求是 - 在执行 UNION ALL 之后,我需要对最终结果中的聚合列求和,按 ProgramId 分组。

我可能会首先使用 UNION 作为 ClientLegacyClient table 作为派生的 table 然后执行 JOINs:

SELECT  C.AwardId, 
        C.ProgramName, 
        COUNT(ClientId) AS Intakes 
FROM (  SELECT  AwardId,
                ProgramName,
                Id
        FROM Client 
        WHERE Id = @ClientId
        UNION 
        SELECT  AwardId,
                ProgramName,
                Id
        FROM LegacyClient
        WHERE Id = @ClientId) C
LEFT JOIN UserRoleEntity URE 
    ON C.AwardId = URE.EntityId 
LEFT JOIN UserRole UR 
    ON URE.UserRoleId = UR.Id AND UR.CDPUserId = @UserId
WHERE (testFunction(@UserId) = 0
  OR (testFunction(@UserId) <> 0 AND UR.CDPUserId = @UserId))
GROUP BY C.AwardId, 
         C.ProgramName;
SELECT C.AwardId, C.ProgramName, Count(ClientId) as Intakes 
FROM
    (
    SELECT Id, AwardId, ProgramName, ClientId FROM Client UNION ALL
    SELECT Id, AwardId, ProgramName, ClientId FROM LegacyClient
    ) C
    LEFT OUTER JOIN UserRoleEntity URE ON C.AwardId = URE.EntityId 
    LEFT OUTER JOIN UserRole UR ON URE.UserRoleId = UR.Id AND UR.CDPUserId = @UserId
WHERE
    C.Id = @ClientId
    AND (testFunction(@UserId) = 0 OR UR.CDPUserId = @UserId)
GROUP BY C.AwardId, C.ProgramName

使用 testFunction() 两次并不是真正必要的(除非 null 是输出之一。)

您可能还希望在联盟之外的 ClientId 上进行过滤。我猜你重写它的目的是为了避免重复的逻辑。您可能仍想看看优化器对哪一个处理得更好。

另外,我用了一个UNION ALL。我在想你想象两个表中的一个只有一个结果。正如您最初写的那样,计数列将纳入并集。

指望 ClientId 似乎很奇怪。一个名为 @ClientId 的参数似乎与 ClientId 列不匹配也是如此。