存储过程联盟所有问题

时间:2012-05-15 18:30:52

标签: tsql stored-procedures union-all

我有一个存储过程,我尝试使用SELECT组合两个不同的UNION ALL语句,但在执行查询后,只返回第一个SELECT中的项目。

我想从第一个和第二个选择语句中获取所有项目。

这就是我所拥有的:

CREATE PROCEDURE [dbo].[Report_AllActivitiesOfficesAll]
    @BeginDate datetime,
    @EndDate datetime
AS
    SET @BeginDate = .dbo.DateOnly(@BeginDate)
    SET @EndDate = .dbo.DateOnly(@EndDate)
BEGIN
    SET NOCOUNT ON;

    SELECT 
          O.OfficeId,
          O.OfficeName AS Name,
          AT.Description AS Activity,
          SUM(A.Duration) AS [Minutes], 
          CAST(SUM(A.Duration) AS FLOAT) / 60 AS [Hours],  
          COUNT(A.ActivityId) AS Activities,
          COUNT(DISTINCT A.CaseId) AS Cases,
          MIN(CAST(A.Duration AS FLOAT) / 60) AS [Min Time],
          MAX(CAST(A.Duration AS FLOAT) / 60) AS [Max Time],
          SUM(CAST(A.Duration AS FLOAT) / 60) / COUNT(A.ActivityId) AS [Avg Time],
          SUM(CAST(A.Duration AS FLOAT) / 60) AS [TotalHours]
      FROM Activity A
          INNER JOIN ActivityType AT ON A.ActivityTypeId = AT.ActivityTypeId
          INNER JOIN ActivityEntry AE ON A.ActivityEntryId = AE.ActivityEntryId
          INNER JOIN [Case] C ON A.CaseId = C.CaseId
          INNER JOIN [Office] O ON AE.OfficeId = O.OfficeId
          INNER JOIN [User] U ON C.CreatedByUserId = U.UserId
      WHERE .dbo.DateOnly(AE.ActivityDate) BETWEEN @BeginDate AND @EndDate 
      GROUP BY 
            O.OfficeId,
            O.OfficeName,
            AT.Description

      UNION ALL

      SELECT 
        O.OfficeId,
        O.OfficeId AS NonCaseOfficeId,
        O.OfficeName AS OfficeName,
        NCAT.Description AS NonCaseActivityType, 
        SUM(NCA.Duration) AS [Minutes],
        CAST(SUM(NCA.Duration) AS FLOAT) / 60 AS [Hours],
        COUNT(NCA.NonCaseActivityId) AS Activities,
        MIN(CAST(NCA.Duration AS FLOAT) / 60) AS [Min Time],
        MAX(CAST(NCA.Duration AS FLOAT) / 60) AS [Max Time],
        SUM(CAST(NCA.Duration AS FLOAT) / 60) / COUNT(NCA.NonCaseActivityId) AS [Avg Time],
        SUM(CAST(NCA.Duration AS FLOAT) / 60) AS [TotalHours]
    FROM NonCaseActivity NCA
        INNER JOIN NonCaseActivityType NCAT ON NCA.NonCaseActivityTypeId = NCAT.NonCaseActivityTypeId
        INNER JOIN [Office] O ON NCA.OfficeId = O.OfficeId
        INNER JOIN [User] U ON NCA.UserId = U.UserId
    WHERE .dbo.DateOnly(NCA.ActivityDate) BETWEEN @BeginDate AND @EndDate
    GROUP BY
        O.OfficeId,
        O.OfficeName,
        NCAT.Description
END

2 个答案:

答案 0 :(得分:2)

列必须与数据类型和内容匹配才能正确有效地使用联合。您无法在中间更改列名称。如果您需要知道记录来自哪个部分,请添加另一个列来执行此操作。你的没有。 Officename位于第一个第二列和第二个查询的第三列。第二个查询的第二列中的内容很可能与第一个查询的第二列的数据类型不同。这不是唯一的错配,而是一个例子。

如果您在第二个查询中需要第一个中不需要的列,则必须将其放在第一个查询中。如果您需要第一个在第二个中不需要的列,则必须在查询中的该位置放置一个空值。例如(不是完全重写你所拥有的,但足以让我知道我在说什么):

SELECT            
    O.OfficeId,    
    CAST(NULL as int) as   NonCaseOfficeId     
    O.OfficeName AS Name,           
    AT.Description AS Activity, 
    COUNT(DISTINCT A.CaseId) AS Cases,
     cast('Case' as varchar (10)) as recordType         
FROM Activity A           
    INNER JOIN ActivityType AT ON A.ActivityTypeId = AT.ActivityTypeId           
    INNER JOIN ActivityEntry AE ON A.ActivityEntryId = AE.ActivityEntryId           
    INNER JOIN [Case] C ON A.CaseId = C.CaseId           
    INNER JOIN [Office] O ON AE.OfficeId = O.OfficeId          
    INNER JOIN [User] U ON C.CreatedByUserId = U.UserId       
WHERE .dbo.DateOnly(AE.ActivityDate) BETWEEN @BeginDate AND @EndDate        
GROUP BY              
    O.OfficeId,             
    O.OfficeName,             
    AT.Description   
UNION ALL        

SELECT          
    O.OfficeId,         
    O.OfficeId,         
    O.OfficeName,         
    NCAT.Description,
    cast(NULL as int),
     'NonCase'  
FROM NonCaseActivity NCA         
    INNER JOIN NonCaseActivityType NCAT 
        ON NCA.NonCaseActivityTypeId = NCAT.NonCaseActivityTypeId
    INNER JOIN [Office] O ON NCA.OfficeId = O.OfficeId         
    INNER JOIN [User] U ON NCA.UserId = U.UserId     
WHERE .dbo.DateOnly(NCA.ActivityDate) BETWEEN @BeginDate AND @EndDate   

既然查询也从第一个查询中获取数据类型,您将看到我专门将其转换为我想要的数据类型。您可能需要在union的第二部分中对null执行此操作,并确保数据类型匹配。我相信如果你没有指定,SQL服务器假定null为int,所以当你想要一些其他数据类型时,这是最重要的。

答案 1 :(得分:0)

对我来说似乎很好。请记住,使用的列名将来自第一个查询。

所以,如果我使用如下的查询:

SELECT 1 AS Something
UNION ALL
SELECT 2 AS SomethingElse

我会在名为Something的字段下看到结果(1和2),并且看不到任何名为SomethingElse的字段的内容。

也许这就是问题?

尝试向两个查询添加额外的字段,以识别它从哪个结果集中提取。

可能为第一个查询添加'Activity'AS Source,为第二个查询添加'Non-Case Activity'AS Source,以确保您能够清楚地看到所显示的内容?