2013-12-04 6 views
0

У меня есть несколько запросов:Объединение нескольких наборов данных в одном запросе

1) select Year , Month, Sum(Stores) from ABC ; 

2)  select Year, Month , Sum(SalesStores) from DEF ; 

3)  slect Year, Month, Sum(Products) from FGH; 

хочу результат, как:

Year, Month , Sum(Stores), Sum(SalesStores), Sum(Products) 

Я попытался Полное внешнее соединение с запросом, который выглядит примерно так:

SELECT ISNULL(x.[Year], y.[Year]) AS [Year], 
ISNULL(x.[Month], y.[Month]) AS [Month], 
x.Sum_Stores, 
y.Sum_SalesStores, 
z.Sum_products 
FROM (select Year , Month, Sum(Stores) AS Sum_Stores from ABC ... GROUP BY [Month]) AS x 
FULL OUTER JOIN (select Year, Month , Sum(SalesStores) AS Sum_SalesStores from DEF ... GROUP BY [Month]) AS y 
    ON x.[Year] = y.[Year] AND x.[Month] = y.[Month] 
FULL OUTER JOIN (select Year, Month , Sum(products) AS Sum_products from FGH ... GROUP BY [Month]) AS z 
ON y.[Year] = z.[Year] AND y.[Month] = z.[Month] 

Проблема заключается в том, что ABC имеет данные только на определенные месяцы, DEF имеет данные для разных месяцев и FGH снова содержит данные за разные месяцы.

Когда я запускаю свой запрос выше, я получаю много нулей и 0.

Может кто-нибудь исправить меня в отношении чего не так с запросом или сказать мне решение, которое работает для моего дела.

+0

Ваш код не содержит 'UNION'. – dav1dsm1th

+0

Спасибо за исправление его полного внешнего соединения – CodeNinja

+0

'select Year, Month, Sum (SalesStores) из DEF' не должны выполняться.Вам не хватает GROUP BY? – usr

ответ

1

Вот еще один способ получить эту информацию. В этом примере представлена ​​короткая настройка для демонстрации этого решения в действии.

CREATE TABLE #ABC([Year] INT, [Month] INT, Stores INT); 
CREATE TABLE #DEF([Year] INT, [Month] INT, SalesStores INT); 
CREATE TABLE #GHI([Year] INT, [Month] INT, Products INT); 

INSERT #ABC VALUES (2013,1,1); 
INSERT #ABC VALUES (2013,1,2); 
INSERT #ABC VALUES (2013,2,3); 

INSERT #DEF VALUES (2013,1,4); 
INSERT #DEF VALUES (2013,1,5); 
INSERT #DEF VALUES (2013,2,6); 

INSERT #GHI VALUES (2013,1,7); 
INSERT #GHI VALUES (2013,1,8); 
INSERT #GHI VALUES (2013,2,9); 
INSERT #GHI VALUES (2013,3,10); 


SELECT 
    T.[Year] 
    ,T.[Month] 
    -- select the sum for each year/month combination using a correlated subquery (each result from the main query causes another data retrieval operation to be run) 
    ,(SELECT SUM(Stores) FROM #ABC WHERE [Year]=T.[Year] AND [Month]=T.[Month]) AS [Sum_Stores] 
    ,(SELECT SUM(SalesStores) FROM #DEF WHERE [Year]=T.[Year] AND [Month]=T.[Month]) AS [Sum_SalesStores] 
    ,(SELECT SUM(Products) FROM #GHI WHERE [Year]=T.[Year] AND [Month]=T.[Month]) AS [Sum_Products] 
FROM (
    -- this selects a list of all possible dates. 
    SELECT [Year],[Month] FROM #ABC 
    UNION 
    SELECT [Year],[Month] FROM #DEF 
    UNION 
    SELECT [Year],[Month] FROM #GHI 
) AS T; 

EDIT: Это может быть обернут в параметризованных хранимой процедуры в соответствии с просьбой:

-- Call proc like this 

--EXEC [getMyReport]; -- params are not required, these will default to NULL if not specified. 
--EXEC [getMyReport] @Year=2013; -- all 2013 data, all months 
--EXEC [getMyReport] @Month=1; -- all January data, from all years 
--EXEC [getMyReport] @Year=2013, @Month=2; -- Feb 2013 data only. 

CREATE PROCEDURE [dbo].[getMyReport] 
    @Year INT = NULL -- default to NULL, this makes the param optional when you exec the procedure. 
    ,@Month INT = NULL 
AS 
BEGIN 
    -- SET NOCOUNT ON added to prevent extra result sets from 
    -- interfering with SELECT statements. 
    SET NOCOUNT ON; 

    SELECT 
     T.[Year] 
     ,T.[Month] 
     -- select the sum for each year/month combination using a correlated subquery (each result from the main query causes another data retrieval operation to be run) 
     ,(SELECT SUM(Stores) FROM #ABC WHERE [Year]=T.[Year] AND [Month]=T.[Month]) AS [Sum_Stores] 
     ,(SELECT SUM(SalesStores) FROM #DEF WHERE [Year]=T.[Year] AND [Month]=T.[Month]) AS [Sum_SalesStores] 
     ,(SELECT SUM(Products) FROM #GHI WHERE [Year]=T.[Year] AND [Month]=T.[Month]) AS [Sum_Products] 
    FROM (
     -- this selects a list of all possible dates. 
     SELECT [Year],[Month] FROM #ABC 
     UNION 
     SELECT [Year],[Month] FROM #DEF 
     UNION 
     SELECT [Year],[Month] FROM #GHI 
    ) AS T 
    WHERE 
     -- if the param IS NULL, then it will not apply filtering 
     -- if the param is specified, then it will filter by year or month 
     (@Year IS NULL OR T.[Year][email protected]) 
     AND 
     (@Month IS NULL OR T.[Month][email protected]) 
    ; 
END 
GO 
+0

Привет, спасибо! , У меня есть две отдельные колонки Year & Month, а не дата (MyDate). Не могли бы вы рассказать мне, как мне нужно изменить ваш запрос для работы в моем случае? – CodeNinja

+0

Пересмотренный ответ, чтобы использовать YEAR & MONTH как отдельные поля INT. – laylarenee

+0

Отличный !! Есть ли способ, которым я могу принять аргумент за месяц и год и посмотреть результаты только до этого месяца ?? Сейчас он отображает данные за все месяцы года. +1 и отмечен как ответ .. – CodeNinja

0
select x,y,z from tableA 
    UNION 
    select x,y,z from tableB 
    UNION 
    select x,y,z from tableC 
+0

Пожалуйста, обратитесь к документации или объясните свой ответ. –

0

Используйте объединение Аллс и группа по сделать это вместо того, чтобы:

select year, month, sum(stores) as sumStores, sum(salesStores) as sumSalesStores, sum(products) as sumProducts 
    from (
     select year, month, stores, salesStores = null, products = null 
     from ABC 

     union all 

     select year, month, stores = null, salesStores, products = null 
     from DEF 

     union all 

     select year, month, stores = null, salesStores = null, products 
     from FGH 
    ) x 
    group by year, month; 
0

Это может быть понятнее использовать такой подход, как: -

select 
    Year, 
    Month, 
    sum(Stores) as Stores, 
    sum(SalesStores) as SalesStores, 
    sum(products) as products 
from (
    select Year, Month, Stores, 0.00 as SalesStores, 0.00 as products 
    from ABC ... 
    union all 
    select Year, Month, 0 as Stores, SalesStores, 0 as products 
    from DEF ... 
    union all 
    select Year, Month, 0 as Stores, 0 as SalesStores, products 
    from FGH ... 
) source 
group by Year, Month 

Первое select заявление в производная таблица определяет ее структуру - и вам может понадобиться cast столбцы-заполнители в этом заявлении для типов правильной точности и масштаба, чтобы позволить данные последующих union s, чтобы не потерять точности.

0

Вот ответ, используя полный объединений:

select 
    coalesce(ABC.Year,DEF.Year,FGH.Year) as Year 
    ,coalesce(ABC.Month,DEF.Month,FGH.Month) as Month 
    ,ABC.Stores 
    ,DEF.SalesStores 
    ,FGH.Products 
from (
    select Year , Month, Sum(Stores) as Stores from ABC group by Year , Month 
) ABC 
full join (
    select Year, Month , Sum(SalesStores) as SalesStores from DEF group by Year , Month 
) DEF 
    on DEF.year = ABC.Year 
    and DEF.Month = ABC.Month 
full join (
    select Year, Month, Sum(Products) as Products from FGH group by Year , Month 
) FGH 
    on (FGH.year = ABC.Year 
    and FGH.Month = ABC.Month) 
    or (FGH.Month = DEF.Year 
    and FGH.Month = DEF.Month) 

SQL Fiddle Demo

0

Вы может объединять множество множеств следующим образом:

SELECT Year, Month, 'Stores' AS Src, Stores AS Value FROM ABC 
UNION ALL 
SELECT Year, Month, 'SalesStores', SalesStores  FROM DEF 
UNION ALL 
SELECT Year, Month, 'Products',  Products  FROM FGH 

затем PIVOT их агрегация:

SELECT 
    Year, 
    Month, 
    Stores, 
    SalesStores, 
    Products 
FROM (
    SELECT Year, Month, 'Stores',  Stores  FROM ABC 
    UNION ALL 
    SELECT Year, Month, 'SalesStores', SalesStores FROM DEF 
    UNION ALL 
    SELECT Year, Month, 'Products', Products FROM FGH 
) AS s (Year, Month, Src, Value) 
PIVOT (
    SUM(Value) FOR Src IN (Stores, SalesStores, Products) 
) AS p 
; 

Или это может быть более эффективным, чтобы первым агрегировать результаты, то объединение агрегированных множеств, то PIVOT:

SELECT 
    Year, 
    Month, 
    Stores, 
    SalesStores, 
    Products 
FROM (
    SELECT Year, Month, 'Stores',  SUM(Stores)  FROM ABC 
    UNION ALL 
    SELECT Year, Month, 'SalesStores', SUM(SalesStores) FROM DEF 
    UNION ALL 
    SELECT Year, Month, 'Products', SUM(Products) FROM FGH 
) AS s (Year, Month, Src, Value) 
PIVOT (
    MAX(Value) FOR Src IN (Stores, SalesStores, Products) 
) AS p 
; 

Как Синтаксис PIVOT требует использования агрегированной функции, мы можем использовать тот, который просто сохраняет уже агрегированное значение (в этом случае оно было MAX).

Смежные вопросы