SQL 匹配日期和产品

SQL Match dates and products

提问人:ProgrammingGirly 提问时间:11/22/2022 最后编辑:ProgrammingGirly 更新时间:11/22/2022 访问量:61

问:

我正在努力寻找一种在 SQL 中创建一个表的方法,在其中我可以合并所有销售日期和可用产品。我的任务是创建一个包含 2022 年 1 月 1 日至 2022 年 12 月 31 日之间的日期范围的表。

我的数据样本包括 2022 年 1 月 1 日至 2022 年 12 月 31 日之间的日期。日期表是我生成年份日期的表格,我必须使用它来匹配我的产品和销售。

CREATE TABLE Date_Table (
    DateID INT     IDENTITY CONSTRAINT PK_Date_Table PRIMARY KEY,
    Date   DATE    NOT NULL,
    Month  TINYINT NOT NULL,
    Year   INT     NOT NULL
);

CREATE TABLE Sales_Table (
    SaleID       INT IDENTITY CONSTRAINT PK_Sales_Table PRIMARY KEY,
    Date_of_Sale DATE NOT NULL,
    Qty_sold     INT NOT NULL,
    Total        MONEY NOT NULL,
    ProductID    INT  NOT NULL CONSTRAINT FK_Product_Table REFERENCES Product_table(ProductID));
);

CREATE TABLE Product_table (
    ProductID     INT IDENTITY CONSTRAINT PK_Product_Table PRIMARY KEY,
    ProductName   NVARCHAR(25) NOT NULL,
    ProductNumber NVARCHAR(25) NOT NULL
);

我还没有找到一种方法来创建一个看起来像这样的表:

日期 产品 “售出数量”
2022-01-01 AB1型 0
2022-01-01 AB2型 2
2022-01-01 AB3型 1
2022-01-01 AB4型 0
2022-01-01 AB5型 2
2022-01-02 AB1型 3
2022-01-02 AB2型 1
2022-01-02 AB3型 0
2022-01-02 AB4型 0
2022-01-02 AB5型 0

因此,我希望所有日期都与所有产品相匹配,即使没有销售。我已经为此工作了一段时间,但我似乎找不到解决方案。如果有人有一点想法可以帮助我开始,我将不胜感激

到目前为止,我只是在我的表之间进行了一些连接,希望完全连接可以让我保留所有必要的数据,但它不起作用。

SQL Server 联接 匹配

评论

2赞 Squirrel 11/22/2022
请不要发布图片。将示例数据以文本形式发布,并包含预期结果
2赞 Dai 11/22/2022
您使用的是哪个版本的 SQL Server?如果您使用的是最新版本,则应使用值并将其转换为日期,然后再使用。GENERATE_SERIES()JOIN
1赞 Dai 11/22/2022
请包括所有列和表的确切列类型和 / 属性。另外,你的是...设计不佳:、 和 列都是多余的,如果管理不当(并且没有任何 S),将包含无效或虚假的信息。CONSTRAINTNULLNOT NULLDate_TableDateIDMonthYearCONSTRAINT
0赞 Dai 11/22/2022
您缺少 、 、 和 的信息。NULLNOT NULLQty_soldTotalProductNameProductNumber

答:

1赞 seanb 11/22/2022 #1

这样做的诀窍是首先创建所有行,然后才使用已售出的数量填充。

创建所有行的最简单方法是执行例如,CROSS JOIN

SELECT Date_Table.[Date], Product_Table.ProductID, Product_Table.ProductName
FROM   Date_Table
       CROSS JOIN Product_Table

上面将为每个产品、每个日期提供一行(因此,如果 365 个产品为 5 天,则为 365 x 5 = 1825 行)。

这样一来,您就可以使用 LEFT JOIN 将其加入到您的实际销售中,这样即使它们在销售中没有匹配项,它也会保留您的初始行。要处理空白行,请使用 ISNULL 将它们设为 0。

SELECT Date_Table.[Date], Product_Table.ProductID, Product_Table.ProductName,
       ISNULL(Sales_Table.Qty_sold, 0) AS Qty_Sold
FROM   (Date_Table
       CROSS JOIN Product_Table)
       LEFT OUTER JOIN Sales_Table ON Date_Table.[Date] = Sales_Table.[Date_of_sale]
               AND Product_Table.ProductID = Sales_Table.ProductID

编辑: 下面是一个包含数据和 SQL 的 db<>fiddle 供您查看

关于数据结构设置的两点说明

  • 你的PK - 我通常会尝试使PK有意义(例如,在日期表中,使用日期作为PK) - 尽管这不是必需的。但是,我建议至少在它们上放置一个非聚集索引,以便您可以直接查找日期(或产品等)。
  • 我还会避免使用作为 SQL 关键字的列名,如日期、月份、年份 - 我还会考虑以更有意义的列命名,例如,不要使用“总计”,而是将其命名为“Total_Revenue”或“Total_Cost”。您的大多数字段都遵循此规则,但是......只是让你知道。

评论

0赞 ProgrammingGirly 11/22/2022
你真是太好了!非常感谢,我真的很感激。