0

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

我想从第一个和第二个 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
4

2 回答 2

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   

现在,由于查询还采用了第一个查询的数据类型,您会看到我专门将它转换为我想要的数据类型。您可能需要在联合的第二部分中的 null 上执行此操作,同时确保数据类型匹配。我相信如果您不指定,SQL 服务器会将 null 假定为 int,因此当您需要其他数据类型时,这一点最重要。

于 2012-05-15T20:17:46.523 回答
0

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

因此,如果我使用如下查询:

SELECT 1 AS Something
UNION ALL
SELECT 2 AS SomethingElse

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

也许这就是问题所在?

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

也许为第一个查询添加“活动”作为源,为第二个查询添加“非案例活动”作为源,只是为了确保您清楚地了解所显示的内容?

于 2012-05-15T18:49:52.260 回答