我有一个存储过程,我尝试使用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
答案 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,以确保您能够清楚地看到所显示的内容?