2014-03-05 27 views
0

我已经阅读了很多关于该主题的文章,但是我无法让它适用于我的案例。T-SQL左连接1行(limi,subselect)

我有以下情况:

  • 的OrderItems(我想主要的数据集)
  • 文章其中有1清单:1关系的订单项目
  • A N: m可加入的“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”。

问题是文章别名与表名具有相同的名称吗?

非常感谢提前对可能的想法, 迈克

+3

这是一个非常不幸的是,糟糕的命名约定打电话给你的表'IDX _......' - 这将直观地指一个** **指标 - 不是表! –

+0

你是对的,但不幸的是,这不是我的数据库,ERP系统的名称是“IDX”,这就是这种命名约定的原因。 – Michael

回答

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 
+0

+1。 。 。谢谢。现在我不必去写它。 –

+0

太棒了! OUTER APPLY解决了问题!非常感谢Lamak! – Michael

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被引用以相同的方式,我们引用相关子查询中的外部查询字段。

0

我看到两个问题。

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

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

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; 

接下来,我重写了第一个查询使用,而不是使用TOP (1)使用ROW_NUMBER您可以控制结果,你想,你不想要的东西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; 
+0

谢谢弗拉基米尔! – Michael

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