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

时间:2014-03-05 19:16:31

标签: sql sql-server tsql join left-join

我已经在该主题上阅读了很多内容,但我无法让它适用于我的案例。

我有以下情况:

  • 订购项目列表(我想要获得的主要数据集)
  • 与订单商品具有1:1关系的商品
  • A 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别名与表名具有相同名称的问题是什么?

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

5 个答案:

答案 0 :(得分:2)

好吧,我更改了你的别名,以及你加入的子查询(我也修改了那个子查询,所以它不再使用隐式连接),虽然这改变了主要是化妆品的地方。实际的重要更改是使用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

答案 1 :(得分:0)

因为下面的查询

而引发错误
 (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的方式与我们在相关子查询中引用外部查询字段的方式相同。

答案 2 :(得分:0)

我看到两个问题。

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

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

答案 3 :(得分:0)

我更喜欢避免嵌套查询。如果可以,我将始终使用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;

答案 4 :(得分:0)

谢谢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