将表中来自多个交叉表的数据关联

Associate data in a table from several crossed tables

提问人:graphene 提问时间:9/11/2023 最后编辑:graphene 更新时间:9/11/2023 访问量:68

问:

我正在使用 SQL Server 2012。

我们有几家公司的订单。每个订单可以有一个或多个销售订单行。 订单行可以有一篇文章,但它永远不会有多篇文章。但是,同一文章可以出现在多个销售订单行中。

Table Order - FinalCustomerId 是 Customer 的外键

Id   FinalCustomerId  Code
1    2                 X45
2    1                 O30
3    2                 Y74
4    5                 XY0

Customer

Id   Name
1    XPTO
2    BOSS
3    TREND
4    XIPS
5    VALLEY
         

文章

Id   Name
1    DVD
2    San Disk
3    CD
4    SPAM

OrderLine(按 OrderId 排序,然后按 Number 排序)- OrderId 是 Order 的外键,如果 FK 为 Article,则为 ArticleId。

Id   Number   OrderId   ArticleId   
1    10       1             1
3    20       1             1
4    30       1             1
7    40       1             2

6    10       2             2
8    20       2             1

2    10       3             2 
5    20       3             2
9    10       4             4

注意:此表有 3 个订单,只有第三个订单有一种类型的文章(id 2)。

CustomerArticleMark - MainArticleId 是 Article 的 FK

Id   FinalCustomerId      MainArticleId   
1           2                    1
2           2                    2
3           1                    3
4           5                    2
5           3                    2
6           5                    4

目标:对于 CustomerArticleMark 的每一行,关联包含该商品的相应销售订单代码。

规则:

  1. CustomerArticleMark 中的文章出现在两个订单的 5 个订单行中,因此主文章必须出现 2 次而不是 5 次;
  2. CustomerArticleMark 中的文章出现在一个订单的 5 个订单行中,因此主文章只能出现一次,而不是 5 次;
  3. CustomerArticleMark 中的 article 不会出现在任何订单行中,因此 Main Article 应该显示,但 Sales Order code 的值为空;
  4. CustomerArticleMark 中的 article 对于 Sales Order 行 per Order 和 order 中的 per FinalCustomer 中的每个不同文章必须是唯一的。有些订单具有相同的商品,但最终客户不同。

从最后一个表开始,所需的结果应为以下结果:

最终表格 - 期望的结果。

Id (of CustomerArticleMark)   FinalCustomer      MainArticle     SALES ORDER Code 
 
    1                               BOSS              DVD                 X45
   
    2                               BOSS              SanDisk             Y74
    3                               XPTO              CD      (there is no o. line with article 3)      
    4                               VALLEY            SanDisk  -
    5                               TREND             SanDisk       (no final customer id5 in Order)
    6                               VALLEY            SPAM                XY0

它应该出现在所有这六行中。只有在 ID 为 3、4 和 5 的行中,销售订单代码必须为空,但其余代码必须填写!

我尝试过使用 T-SQL:

SELECT DISTINCT  
                   {CustomerArticleMark}.[Id]
                ,  {Customer}.[Name] AS FinalCustomer
                ,  {Article}.[Name] AS MainArticle
                ,  {Order}.[Code] AS SALES ORDER Code
                
             
                FROM {CustomerArticleMark} 
                LEFT JOIN {Customer} ON {Customer}.[Id] = {CustomerArticleMark}.[FinalCustomerId] 
                LEFT JOIN {Article} ON {Article}.[Id] = {CustomerArticleMark}.[MainArticleId] 
                LEFT JOIN {SalesOrderLine} ON {SalesOrderLine}.[ArticleId] = {Article}.[Id]
                LEFT JOIN {Order} ON {Order}.[Id] = {SalesOrderLine}.[OrderId]
                WHERE {Order}.[FinalCustomerId] = {CustomerArticleMark}.[FinalCustomerId]

我明白了:

Id (of CustomerArticleMark)   FinalCustomer      MainArticle     SALES ORDER Code 
 
    1                               BOSS              DVD                 X45
    1                               BOSS              SanDisk*            X45*
    
    2                               BOSS              SanDisk             Y74
    6                               VALLEY            SPAM                XY0

它没有显示 3、4 和 5,但应该显示销售订单代码为空。

差异用星号标记。我们怎样才能得到想要的结果? 感谢您的关注。

Database T-SQL SQL-SERVER-2012

评论


答:

2赞 Nandalal Seth 9/11/2023 #1

好的,由于 SalesOrderLine 直接链接到 Order,我们应该将它们视为单个实体。然后我们可以将其加入 CustomerArticleMark。请尝试以下...

SELECT DISTINCT  
                   {CustomerArticleMark}.[Id]
                ,  {Customer}.[Name] AS FinalCustomer
                ,  {Article}.[Name] AS MainArticle
                ,  {Order}.[Code] AS SALES ORDER Code
                
             
                FROM {CustomerArticleMark} 
                LEFT JOIN ( {SalesOrderLine} INNER JOIN {Order} ON {Order}.[Id] = {SalesOrderLine}.[OrderId]) ON {SalesOrderLine}.[ArticleId] = {CustomerArticleMark}.[MainArticleId]
                AND {Order}.[FinalCustomerId] = {CustomerArticleMark}.[FinalCustomerId]
                LEFT JOIN {Customer} ON {Customer}.[Id] = {CustomerArticleMark}.[FinalCustomerId] 
                LEFT JOIN {Article} ON {Article}.[Id] = {CustomerArticleMark}.[MainArticleId] 

此外,在您想要的结果中,我认为您不能有以下内容,因为 MainArticleId/FinalCustomerId 没有匹配的 Orderline/Order -

Id (of CustomerArticleMark)   FinalCustomer      MainArticle     SALES ORDER Code 

1                               BOSS              DVD                 Y74 
6                               VALLEY            SPAM                XY0

或者,如果你想使用 CTE(我也在下面使用了 GROUP BY,你可以使用 DISTICNT)

;WITH cte as (
SELECT [SalesOrderLine].[ArticleId] , [Order].[FinalCustomerId] , [Order].[Code]  FROM [SalesOrderLine] INNER JOIN [Order] ON [Order].[Id] = [SalesOrderLine].[OrderId])
SELECT 
                   [CustomerArticleMark].[Id]
                ,  [Customer].[Name] AS FinalCustomer
                ,  [Article].[Name] AS MainArticle
                ,  [cte].[Code] AS [SALES ORDER Code]
                
                FROM [CustomerArticleMark] 
                LEFT JOIN [cte] ON [cte].[ArticleId] = [CustomerArticleMark].[MainArticleId]
                AND [cte].[FinalCustomerId] = [CustomerArticleMark].[FinalCustomerId]
                JOIN [Customer] ON [Customer].[Id] = [CustomerArticleMark].[FinalCustomerId] 
                JOIN [Article] ON [Article].[Id] = [CustomerArticleMark].[MainArticleId] 
GROUP BY             [CustomerArticleMark].[Id]
                ,  [Customer].[Name] 
                ,  [Article].[Name] 
                ,  [cte].[Code]

评论

0赞 graphene 9/11/2023
它还没有解决问题。但是谢谢。
0赞 Nandalal Seth 9/11/2023
@graphene,我已经更新了我之前的答案。让我知道这是否有帮助?谢谢
1赞 Nandalal Seth 9/11/2023
@graphene。Customer 和 Article 表直接在外部联接到 CustomerArticleMark,因此它们不可能为空。我刚刚尝试过,它有效。你想发布你正在尝试的确切查询吗?
1赞 Nandalal Seth 9/11/2023
是的,CTE 会起作用。它可能更具可读性,但从性能上讲,我认为它不会给出更好的结果。您也可以尝试使用 GROUP BY 而不是 DISTINCT。
1赞 Nandalal Seth 9/11/2023
我已经用 CTE 更新了答案。如果有帮助,请告诉我。谢谢