给出以下(大大简化)表:
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并不重要,但输出中每个标签只能有一个实例。
最有效的方法是什么?
我无法改变数据库架构。
答案 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