繁体   English   中英

T-SQL左连接1行(limi,subselect)

[英]T-SQL Left-Join with 1 row (limi, subselect)

我已经阅读了很多关于该主题但我无法让它适用于我的案例。

我有以下情况:

  • 订单项目列表(我想要的主要数据集)
  • 与订单商品具有1:1关系的商品
  • 一个n:m Jointable“Articlesupplier”,它创建了一篇文章和一个合作伙伴之间的关系
  • 包含合作伙伴详细信息的合作伙伴表。

目标:
每个OrderItem和供应商的一个数据集我只想获得在连接中找到的第一个数据集。 无需优先处理。

表:

IDX_ORDERITEM

id,article_id

IDX_ARTICLE

id,name

IDX_ARTICLESUPPLIER

article_id,partner_id

IDX_PARTNER

id,abbr

我的实际陈述(简短版):

SELECT IDX_ORDERITEM.id
FROM         
dbo.IDX_ORDERITEM AS IDX_ORDERITEM

-- ARTICLE --
INNER JOIN dbo.IDX_ARTICLE AS IDX_ARTICLE
ON IDX_ORDERITEM.article_id=IDX_ARTICLE.id

-- SUPPLIER VIA ARTICLE --  
LEFT JOIN 
  (SELECT TOP(1) IDX_PARTNER.id, IDX_PARTNER.abbr 
  FROM IDX_PARTNER, IDX_ARTICLESUPPLIER
  WHERE IDX_PARTNER.id = IDX_ARTICLESUPPLIER.partner_id
  AND IDX_ARTICLESUPPLIER.article_id=IDX_ARTICLE.id) AS IDX_PARTNER_SUPPLIER 
  ON IDX_PARTNER_SUPPLIER.id=IDX_ARTICLE.supplier_partner_id

WHERE 1>0
ORDER BY orderitem.id DESC

但似乎我无法访问子查询中的IDX_ARTICLE.id。 我收到以下错误消息:

无法绑定多部分标识符“IDX_ARTICLE.id”。

Article别名与表名具有相同名称的问题是什么?

迈克,非常感谢您提出可能的想法

好吧,我更改了你的别名,以及你加入的子查询(我也修改了那个子查询,所以它不再使用隐式连接),尽管这改变了主要是化妆品的地方。 实际的重要变化是使用OUTER APPLY而不是LEFT JOIN

SELECT OI.id
FROM dbo.IDX_ORDERITEM AS OI
INNER JOIN dbo.IDX_ARTICLE AS A
    ON OI.article_id = A.id
OUTER APPLY  
  (SELECT TOP(1) P.id, P.abbr 
   FROM IDX_PARTNER AS P
   INNER JOIN IDX_ARTICLESUPPLIER AS SUP
        ON P.id = SUP.partner_id
   WHERE SUP.article_id = A.id
   AND P.id = A.supplier_partner_id) AS PS 
ORDER BY OI.id DESC

抛出错误是因为下面的查询

 (SELECT TOP(1) IDX_PARTNER.id, IDX_PARTNER.abbr 
  FROM IDX_PARTNER, IDX_ARTICLESUPPLIER
  WHERE IDX_PARTNER.id = IDX_ARTICLESUPPLIER.partner_id
  AND IDX_ARTICLESUPPLIER.article_id=IDX_ARTICLE.id) AS IDX_PARTNER_SUPPLIER 

不能将其视为相关子查询, IDX_ARTICLE.id在其中引用的方式与我们在相关子查询中引用外部查询字段的方式相同。

我看到两个问题。

根据您的DDL,没有IDX_ARTICLE.supplier_partner_id,您在左连接on子句中引用它。

其次,我很确定你不能在派生表中使用IDX_ARTICLE.id。 只需将IDX_ARTICLESUPPLIER.article_id添加到派生表中的选定字段,并在针对IDX_ARTICLE.id的左连接on子句中使用它。

我更喜欢避免嵌套查询。 如果可以,我将始终使用CTE重写它。

WITH    Part_Sup
          AS (
               SELECT TOP ( 1 ) P.id
                   ,P.abbr
                   ,SUP.article_id
                FROM IDX_PARTNER AS P
                INNER JOIN IDX_ARTICLESUPPLIER AS SUP
                    ON P.id = SUP.partner_id
             )
    SELECT OI.id
        FROM dbo.IDX_ORDERITEM AS OI
        INNER JOIN dbo.IDX_ARTICLE AS A
            ON OI.article_id = A.id
        LEFT OUTER JOIN Part_Sup AS PS
            ON PS.article_id = A.Id
               AND PS.id = A.supplier_partner_id
        ORDER BY OI.id DESC;

接下来,我重写了第一个查询以使用ROW_NUMBER()函数而不是使用TOP (1)使用ROW_NUMBER您可以控制您想要的结果和您不想要的结果。

WITH    Part_Sup
          AS (
               SELECT P.id
                   ,P.abbr
                   ,SUP.article_id
                   ,ROW_NUMBER() OVER ( PARTITION BY P.id, P.abbr ) AS RowNum
                FROM IDX_PARTNER AS P
                INNER JOIN IDX_ARTICLESUPPLIER AS SUP
                    ON P.id = SUP.partner_id
             )
    SELECT OI.id
        FROM dbo.IDX_ORDERITEM AS OI
        INNER JOIN dbo.IDX_ARTICLE AS A
            ON OI.article_id = A.id
        LEFT OUTER JOIN Part_Sup AS PS
            ON PS.article_id = A.Id
               AND PS.id = A.supplier_partner_id
               AND RowNum = 1
        ORDER BY OI.id DESC;

谢谢Lamak - 你解决了它:)我使用你的输入提取基本解决方案,使其更容易阅读其他有相同问题的人:

使用OUTER APPLY(此处没有ORDER_ITEM表):

SELECT IDX_ARTICLE.id AS AR_ID, IDX_PARTNER_SUPPLIER.id, IDX_PARTNER_SUPPLIER.abbr
FROM         
dbo.IDX_ARTICLE AS IDX_ARTICLE

OUTER APPLY
    (SELECT TOP(1) _PARTNER.id, _PARTNER.abbr
    FROM IDX_PARTNER AS _PARTNER
    INNER JOIN IDX_ARTICLESUPPLIER AS _ARTICLESUPPLIER
        ON _PARTNER.id = _ARTICLESUPPLIER.partner_id
    WHERE _ARTICLESUPPLIER.article_id=IDX_ARTICLE.id
    AND _ARTICLESUPPLIER.deleted IS NULL) AS IDX_PARTNER_SUPPLIER

WHERE IDX_ARTICLE.id=67

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM