两个临时表上的完全联接不返回所有结果 SQL Server

发布于 2024-11-29 13:51:28 字数 3908 浏览 2 评论 0原文

更新:我已经包含了可以粘贴到 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

UPDATE: I've included complete code that can be pasted into SSRS, to show the results.

We report on lots of date-centric information and have to produce reports from it. Some of the source data isn't updated in a timely manner but to ensure the reports are neat and can share the same date columns we sometimes use a CTE above the query to generate a list of the last 13 months. One server is still using SQL Server 2000 so CTE's aren't possible. I've tried populating two temporary tables and using a full join but it seems to treat it as an inner join. Here is the representative query:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

甜警司 2024-12-06 13:51:28

您有一个 where 子句显式#TEMP _STAGING 选择 date 列,从而有效地过滤掉 #TEMP_LAST13MONTHS 中的每一行code> 在 #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

来返回您需要的每一行。 (我个人的偏好是第一个选择,尽管更长)

You have a where clause explicitly selecting the date column from #TEMP _STAGING, thus effectively filtering out every row from #TEMP_LAST13MONTHS that doesn't have a corresponding row in #TEMP_STAGING

Changing your where clause to

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

should be enough (and using a FULL OUTER JOIN)

Edit

You could use either this

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

or this

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

to return every row your require. (My personel prefercene is, albeit longer, the first option)

白日梦 2024-12-06 13:51:28

试试这个(我已经更新了一点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”无效。

Try this (I've updated the sql a little):

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

I'm sorry I can't be more helpful than to ask you to try the above as I get the following error when running your script:

Msg 208, Level 16, State 1, Line 26 Invalid object name 'dDate'.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文