对于表中的每一行,获取另一个表中的任何一个链接行

时间:2010-07-30 10:40:48

标签: sql sql-server sql-server-2005

给出以下(大大简化)表:

create table Tags (
   TagId int Primary Key
)

create table OrderLines (
   Branch int,
   Station int,
   TransNo int,
   TagId int foreign key references Tags,
   primary key (Branch, Station, TransNo)
)

我需要一个标签列表以及一个引用每个标签的OrderLine。我期望零或一个OrderLines引用每个Tag,但数据库约束中没有任何内容可以强制执行此操作。

给出这样的输入:

 OrderLines                                     Tags
 Branch Station TransNo TagId                   TagId
 1      100     2345    1                       1
 1      100     2346    1                       2
 1      101     5223    2                       3
 3      100     6677    4                       4

我想得到这样的输出:

  TagId     Branch    Station    TransNo  
  1         1         100        2345     <-- it could list 2346 here, don't care
  2         1         101        5223     
  3         null      null       null
  4         3         100        6677

请注意,尽管TagId 1被引用了两次,但我的输出只包含其中一个。排除哪个OrderLine并不重要,但输出中每个标签只能有一个实例。

最有效的方法是什么?

我无法改变数据库架构。

4 个答案:

答案 0 :(得分:2)

您必须查看执行计划以衡量效率

;WITH O AS
(
SELECT Branch, Station, TransNo, TagId,
ROW_NUMBER() OVER (PARTITION BY TagId ORDER BY TagId ) AS RN
FROM OrderLines
)
    SELECT T.TagID, O.Branch, O.Station, O.TransNo
        FROM Tags T
        LEFT JOIN O ON T.TagID = O.TagID and RN=1

答案 1 :(得分:2)

select t.TagId, t.Station, t.Branch, t.TransNo
from (
SELECT Station, Branch, TransNo, TagId, ROW_NUMBER() OVER (partition by TagId order by TagId) r
From OrderLines) t
WHERE r = 1
UNION ALL
SELECT TagId, NULL, NULL, NULL
from Tags
WHERE NOT EXISTS (Select 1 from OrderLines ol Where ol.TagId = Tags.Id)

答案 2 :(得分:0)

SELECT Tags.TagID, Branch, Station, TransNo
    FROM Tags
    LEFT JOIN OrderLines ON Tags.TagID = OrderLines.TagID
    ORDER BY Tags.TagID

左连接将确保列出所有标签,即使那些没有连接任何订单行的标签也是如此。 唯一的缺陷是,如果多个订单行引用标记,则每个订单行将标记一次标记。某些DBMS(例如MySQL)允许您使用GROUP BY解决此问题,并且仍然选择不分组的列,但它是非标准的,并且无法保证您将获得哪个OrderLine。如果你想要这个,你将不得不求助于子查询,联合,临时表或视图(但由于你不能改变架构,最后一个选项已经出局)。

答案 3 :(得分:0)

   select
        T.tagid,
        O.branch,
        O.station,
        O.transno
    from orderlines O
    right join tags T on (t.tagid=O.tagid)
    group by t.tagid

结果:

  tagid branch  station transno
1   1   100 2345
2   1   101 5223
3   NULL    NULL    NULL
4   3   100 6677