2012-05-15 1 views
0

У меня есть хранимая процедура, в которой я пытаюсь объединить два разных оператора SELECT, используя UNION ALL, но после выполнения запроса возвращаются только элементы из первого SELECT.Сохраненная процедура Union All issue

Я хотел получить все элементы как из первых, так и из вторых операторов выбора.

Вот что у меня есть:

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

Опубликовать всю хранимую процедуру, должно быть что-то не так. – Magnus

+0

@Magnus Я только что добавил полный код с последними изменениями. – Masriyah

+0

У вас по 11 столбцов каждый, но каждый тип данных столбца должен быть одинаковым. У вас есть несколько столбцов, которые не * появляются * одинакового типа данных. –

ответ

2

Столбцы должны соответствовать типу и типу данных, чтобы правильно и эффективно использовать соединение. Вы не можете изменять имена столбцов посередине. Если вам нужно знать, какая часть профсоюза взяла запись, добавьте еще один столбец для этого. Нет. Имя сотрудника находится во втором столбце в первом и третьем столбцах во втором запросе. То, что во втором столбце второго запроса, скорее всего, не будет тем же самым типом данных, что и второй столбец первого. Это не единственное несоответствие, а пример.

Если вам нужен столбец во втором запросе, который вам не нужен в первом, вы все равно должны поместить его в первый запрос. И если вам нужен столбец в первом, который вам не нужен во второй, вы должны поместить нулевое значение в это место в запросе. Например (не полное переписывание того, что у вас есть, но достаточно, чтобы получить представление о том, что я имею в виду):

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-сервер является int, если вы не укажете, так что это наиболее важно, когда вам нужен другой тип данных.

+0

Спасибо за отличное объяснение, я действительно ценю это. Но так я понимаю: оба оператора select должны иметь одинаковый тип данных, а также именование? – Masriyah

+2

@Amina, типы данных должны совпадать, но имена будут использовать все, что было в первом запросе. –

+0

@KevinFairchild спасибо за подсказку, что хранимая процедура выполняет отлично, но теперь я получаю все действия в случае столбца активности без операции. Все результаты от операторов неактивной активности и операторов выбора активности в случае перечислены в именах столбцов неточечной активности. Как я могу получить так, что каждый оператор select имеет свой собственный набор имен столбцов? Спасибо – Masriyah

0

Кажется, хорошо для меня. Имейте в виду, что используемые имена столбцов будут получены из первого запроса.

Так что, если я использовал запрос как:

SELECT 1 AS Something 
UNION ALL 
SELECT 2 AS SomethingElse 

Я вижу только результаты (1 и 2) в поле называется что-то и не видел бы ничего для поля под названием SomethingElse.

Возможно, это проблема?

Попробуйте добавить дополнительное поле к обоим запросам, которые идентифицируют, с каких результатов он вытягивает.

Возможно, добавьте источник AS для первого запроса и источник AS для второго запроса, а не для того, чтобы убедиться, что вы получаете четкое представление о том, что отображается?

+0

Хорошо, я продолжу и попробую и посмотрю. Благодаря! – Masriyah

+0

Пробовал это, и кажется, что все элементы, возвращенные из этого, являются элементами выбора из 1-го оператора выбора и ничего из второго. – Masriyah

+0

Вы попытались запустить второй выбор напрямую? –