在做了一些观察之后,我想也许我在这里找到了一个解决方案:sql join including null and non existing records。交叉加入我的桌子似乎是解决我的问题的好方法,但现在我遇到了障碍:
以下是我正在使用的表格:
CREATE TABLE [dbo].[DCRSales](
[WorkingDate] [smalldatetime] NOT NULL,
[Store] [int] NOT NULL,
[Department] [int] NOT NULL,
[NetSales] [money] NOT NULL,
[DSID] [int] IDENTITY(1,1) NOT NULL)
CREATE TABLE [dbo].[Stores](
[Number] [int] NOT NULL,
[Has_Deli] [bit] NOT NULL,
[Alcohol_Register] [int] NULL,
[Is_Cost_Saver] [bit] NOT NULL,
[Store_Status] [nchar](10) NOT NULL,
[Supervisor_Number] [int] NOT NULL,
[Email_Address] [nchar](20) NOT NULL,
[Sales_Area] [int] NULL,
[PZ_Store_Number] [int] NULL,
[Has_SCO] [bit] NULL,
[SCO_Reg] [nchar](25) NULL,
[Has_Ace] [bit] NULL,
[Ace_Sq_Ft] [int] NULL,
[Open_Date] [datetime] NULL,
[Specialist] [nchar](2) NULL,
[StateID] [int] NOT NULL)
CREATE TABLE [dbo].[DepartmentMap](
[Department_Number] [int] NOT NULL,
[Description] [nvarchar](max) NOT NULL,
[Parent_Department] [int] NOT NULL)
CREATE TABLE [dbo].[ParentDepartments](
[Parent_Department] [int] NOT NULL,
[Description] [varchar](50) NULL
DCRSales是一个包含新数据和归档数据的表。存档的数据并不完美,这意味着当然存在某些缺失的日期差距,而且一些商店目前拥有一个他们没有或不再拥有他们曾经拥有的部门的部门。我的目标是将此表连接到我们的部门列表,列出子部门和父部门,并在给定日期范围内整理netsales。如果商店在该日期范围内没有任何部门,我仍然需要将其显示为0.00。
更强大的解决方案可能只是存储每个商店的所有部门,无论他们是否拥有该部门(当然销售额设置为0.00)。但是我想这样做和/或在这里解决我的问题无论如何都需要非常类似的查询。
我尝试的查询如下:
WITH CTE AS (
SELECT S.Number as Store, DepartmentMap.Department_Number as Department, ParentDepartments.Parent_Department as Parent, ParentDepartments.Description as ParentDescription, DepartmentMap.Description as ChildDescription
FROM Stores as S CROSS JOIN dbo.DepartmentMap INNER JOIN ParentDepartments ON DepartmentMap.Parent_Department = ParentDepartments.Parent_Department
WHERE S.Number IN(<STORES>) AND Department_Number IN(<DEPTS>)
)
SELECT CTE.Store, CTE.Department, SUM(ISNULL(DCRSales.NetSales, 0.00)) as Sales, CTE.Parent, CTE.ParentDescription, CTE.ChildDescription
FROM CTE LEFT JOIN DCRSales ON DCRSales.Department = CTE.Department AND DCRSales.Store = CTE.Store
WHERE DCRSales.WorkingDate BETWEEN '<FIRSTDAY>' AND '<LASTDAY>' OR DCRSales.WorkingDate IS NULL
GROUP BY CTE.Store, CTE.Department, CTE.Parent, CTE.ParentDescription, CTE.ChildDescription
ORDER BY CTE.Store ASC, CTE.Department ASC
在这个查询中,我尝试将每个部门CROSS JOIN连接到Stores表中的商店,以便我可以获得每个商店和每个部门的组合。我还包括每个部门的家长部门以及子部门的描述和父部门的描述。我根据商店和部门过滤了第一部分,但这并没有改变一般概念。
使用此结果集,然后我尝试将此表连接到DCRSales中特定日期范围内的所有销售。我还包括日期,如果它为null,因为具有NULL销售的结果也具有NULL WorkingDate。
此查询似乎有效,直到我注意到并非所有部门都与所有商店一起使用。特别是没有与所有部门合并的商店是那些在给定日期范围内没有数据的商店(意味着他们已经关闭)。如果部门没有数据,则仍应列出其部门编号,父编号,部门描述和父描述(销售额为0.00)。非常感谢任何帮助。
答案 0 :(得分:2)
您的WHERE
条款会过滤掉某些时间点有销售记录的记录,但不会过滤所需的时间段,这些记录不符合任何一个标准,因此被排除在外。
我可能会低估它,但可能只需要移动:
DCRSales.WorkingDate BETWEEN '<FIRSTDAY>' AND '<LASTDAY>'
符合LEFT JOIN
条件并删除WHERE
条款。如果这不对,您可以在加入前的第二个cte中按日期过滤销售。
答案 1 :(得分:0)
你想要的是一个外部联接。
请参阅:https://technet.microsoft.com/en-us/library/ms187518(v=sql.105).aspx
答案 2 :(得分:0)
我建议这个过程可能很多太复杂,无法使用单个查询完成。我认为您需要执行多个查询:将感兴趣的事务提取到单独的表中,然后在使用该表生成最终统计信息之前在该表中修改结果一次或多次。一个存储过程驱动几个单独存储的查询,可用于驱动该过程,该过程在几个“阶段”中对初始提取的数据进行多次“传递”。
例如,一条重要信息就是知道某个商店有特定部门时 。 (例如:store, department, starting_date, ending_date
。)这将是对可能存在的表(并且可能从中绘制...)的细化,其中列出了特定商店的哪些部门< EM>今天。
让我们希望部门编号不会更改,或您的公司没有收购其他公司,因此需要以某种方式“重新映射”这些数字。
另外:坦率地说,如果您可以访问一个非常好的统计包,例如SAS®或SPSS®...... 可以“R”做这类事情吗? / em> ...你可能会发现自己更富裕了。 (不,我不是指“Microsoft Excel ...”); - )
当我遇到像这些(我已经多次......)这样的要求时,stats-package是不可或缺的。我发现我必须多次“按摩”过程和提取的数据,在一个连续细化的系统中逐渐引导我进行一个我可以信任并因此保护的报告过程。