Полное объединение двух временных таблиц не возвращает все результаты SQL Server - PullRequest
1 голос
/ 11 августа 2011

ОБНОВЛЕНИЕ: я включил полный код, который можно вставить в SSRS, чтобы показать результаты.

Мы сообщаем о большом количестве информации, ориентированной на дату, и должны составлять отчеты из нее. Некоторые из исходных данных не обновляются своевременно, но для того, чтобы отчеты были аккуратными и могли иметь одинаковые столбцы с датами, мы иногда используем CTE над запросом для создания списка за последние 13 месяцев. Один сервер все еще использует SQL Server 2000, поэтому использование CTE невозможно. Я попытался заполнить две временные таблицы и использовать полное соединение, но похоже, что оно рассматривается как внутреннее соединение. Вот типичный запрос:

set DATEFORMAT ymd

IF object_id('tempdb..#EXAMPLE_SOURCE_DATA') is not null 
BEGIN    
  DROP TABLE #EXAMPLE_SOURCE_DATA
END

IF object_id('tempdb..#TEMP_STAGING') is not null 
BEGIN    
  DROP TABLE #TEMP_STAGING
END

IF object_id('tempdb..#TEMP_LAST13MONTHS') is not null 
BEGIN    
  DROP TABLE #TEMP_LAST13MONTHS
END

--This would normally be real data, but use a temporary for testing/bug fixing
CREATE TABLE #EXAMPLE_SOURCE_DATA(
   Date datetime,
   Actual float,
)

CREATE TABLE #TEMP_STAGING(
   Date datetime,
   Actual float,
)

CREATE TABLE #TEMP_LAST13MONTHS(
   Date13 datetime,
)

INSERT INTO #EXAMPLE_SOURCE_DATA VALUES ('2011-06-27 12:34:56', 56.56)
INSERT INTO #EXAMPLE_SOURCE_DATA VALUES ('2011-05-23 12:34:56', 45.45)
INSERT INTO #EXAMPLE_SOURCE_DATA VALUES ('2011-04-11 12:34:56', 23.23)
INSERT INTO #EXAMPLE_SOURCE_DATA VALUES ('2011-03-03 12:34:56', 12.12)
INSERT INTO #EXAMPLE_SOURCE_DATA VALUES ('2011-02-01 12:34:56', 12.12)
INSERT INTO #EXAMPLE_SOURCE_DATA VALUES ('2011-01-23 12:34:56', 45.45)
INSERT INTO #EXAMPLE_SOURCE_DATA VALUES ('2011-04-11 12:34:56', 23.23)
INSERT INTO #EXAMPLE_SOURCE_DATA VALUES ('2011-03-03 12:34:56', 12.12)
INSERT INTO #EXAMPLE_SOURCE_DATA VALUES ('2011-02-01 12:34:56', 67.67)
INSERT INTO #EXAMPLE_SOURCE_DATA VALUES ('2011-01-05 12:34:56', 56.56)
INSERT INTO #EXAMPLE_SOURCE_DATA VALUES ('2011-02-01 12:34:56', 67.67)
INSERT INTO #EXAMPLE_SOURCE_DATA VALUES ('2010-12-05 12:34:56', 78.78)

-- Copy data to a temp table but 'flatten' the Date into beginning of month, to allow comparison and join.
INSERT INTO #TEMP_STAGING (Date, Actual)
SELECT 
  CAST(CAST(DATEPART(Year,Date) AS varchar) + '-' + CAST(DATEPART(Month,Date) AS varchar) + CAST('-01 00:00:00' as varchar) AS datetime) AS Date,
  Actual
FROM #EXAMPLE_SOURCE_DATA

--Insert rolling 13 months into a date table
INSERT INTO #TEMP_LAST13MONTHS VALUES (DATEADD(MONTH,-1,DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()),0)))
INSERT INTO #TEMP_LAST13MONTHS VALUES (DATEADD(MONTH,-2,DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()),0)))
INSERT INTO #TEMP_LAST13MONTHS VALUES (DATEADD(MONTH,-3,DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()),0)))
INSERT INTO #TEMP_LAST13MONTHS VALUES (DATEADD(MONTH,-4,DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()),0)))
INSERT INTO #TEMP_LAST13MONTHS VALUES (DATEADD(MONTH,-5,DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()),0)))
INSERT INTO #TEMP_LAST13MONTHS VALUES (DATEADD(MONTH,-6,DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()),0)))
INSERT INTO #TEMP_LAST13MONTHS VALUES (DATEADD(MONTH,-7,DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()),0)))
INSERT INTO #TEMP_LAST13MONTHS VALUES (DATEADD(MONTH,-8,DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()),0)))
INSERT INTO #TEMP_LAST13MONTHS VALUES (DATEADD(MONTH,-9,DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()),0)))
INSERT INTO #TEMP_LAST13MONTHS VALUES (DATEADD(MONTH,-10,DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()),0)))
INSERT INTO #TEMP_LAST13MONTHS VALUES (DATEADD(MONTH,-11,DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()),0)))
INSERT INTO #TEMP_LAST13MONTHS VALUES (DATEADD(MONTH,-12,DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()),0)))
INSERT INTO #TEMP_LAST13MONTHS VALUES (DATEADD(MONTH,-13,DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()),0)))

-- DEBUG
--/*
SELECT * FROM #TEMP_LAST13MONTHS ORDER BY Date13 DESC
SELECT * FROM #EXAMPLE_SOURCE_DATA ORDER BY Date DESC
SELECT * FROM #TEMP_STAGING ORDER BY Date DESC
--*/

--This doesn't return values against 2011-07-01 or before 2010-12-01 ??? (Date this 

was written 2011-08)
SELECT
  Date,
  SUM(Actual)
FROM #TEMP_LAST13MONTHS
FULL OUTER JOIN #TEMP_STAGING ON #TEMP_LAST13MONTHS.Date13 = #TEMP_STAGING.Date
GROUP BY Date
ORDER BY Date DESC

Ответы [ 2 ]

1 голос
/ 11 августа 2011

У вас есть предложение where , явно , выбирающее столбец date из #TEMP _STAGING, таким образом, эффективно отфильтровывая каждую строку из #TEMP_LAST13MONTHS, у которой нет соответствующей строки в #TEMP_STAGING

Достаточно изменить условие where на

(COALESCE(Date, Date13) BETWEEN @StartOfMonthlyReporting AND @EndOfMonthlyReporting)

(и использовать FULL OUTER JOIN)

Редактировать

Вы можетеиспользуйте либо

SELECT  [Date]
        , SUM([Actual])
FROM    (       
            SELECT  [Date] = COALESCE(#TEMP_STAGING.Date, #TEMP_LAST13MONTHS.Date13)
                    , [Actual] = COALESCE(Actual, 0)
            FROM    #TEMP_LAST13MONTHS 
                    FULL OUTER JOIN #TEMP_STAGING ON #TEMP_LAST13MONTHS.Date13 = #TEMP_STAGING.Date
        ) q
GROUP BY 
        Date
ORDER BY 
        Date DESC

, либо

SELECT  [Date] = COALESCE(#TEMP_STAGING.Date, #TEMP_LAST13MONTHS.Date13)
        , [Actual] = SUM(COALESCE(Actual, 0))
FROM    #TEMP_LAST13MONTHS 
        FULL OUTER JOIN #TEMP_STAGING ON #TEMP_LAST13MONTHS.Date13 = #TEMP_STAGING.Date
GROUP BY
        COALESCE(#TEMP_STAGING.Date, #TEMP_LAST13MONTHS.Date13)
ORDER BY
        1 DESC

, чтобы вернуть все строки, которые вам нужны.(Мой личный предпочтительный, хотя и дольше, первый вариант)

0 голосов
/ 11 августа 2011

Попробуйте это (я немного обновил sql):

SELECT  Date,
        LEFT(CAST(DATENAME(Month, Date) AS NVARCHAR), 3) + ' ' + CAST(YEAR(Date) AS NVARCHAR) AS MonthYear
FROM    [#TEMP_LAST13MONTHS]
        LEFT OUTER JOIN [#TEMP_STAGING]
            ON [#TEMP_LAST13MONTHS].Date13 = [#TEMP_STAGING].Date
WHERE   Date IS NULL OR (Date BETWEEN @StartOfMonthlyReporting AND @EndOfMonthlyReporting)
ORDER BY Date DESC

Извините, я не могу быть более полезным, чем попросить вас попробовать описанное выше, так как я получаю следующую ошибку при запуске вашего скрипта:

Сообщение 208, Уровень 16, Состояние 1, Строка 26 Неверное имя объекта 'dDate'.

...