更好地连接表以从一个或另一个表中选择数据的方法

时间:2014-06-10 20:58:22

标签: sql sql-server join

BookID  Title           ReleaseYear
1       The Hobbit      1937
2       Atlas Shrugged  1957

BookID  Cost    BookPrinterID
1       12      38

BookID  Charge  BookPublisherID
1       39      148
2       45      151

这是我出版的表格数据 书籍表,成本表和收费表 我希望看到成本信息,如果存在其他收费来自单个查询。即。

BookID  Cost
1       12
2       45

这是我的查询

select Books.BookID, ISNULL(Cost.Cost, Charge.Charge) AS Cost 
from Books
left join Cost on Books.BookID = Cost.BookID
left join Charge on Book.BookID = Charge.BookID

这样可行,但问题是如果有更多的表要连接或要检索更多的列,每个列的ISNULL条件将成为一大块文本,特别是如果你必须解析xml。

ISNULL(Cost.Xchange.value('/Partner[1]/@Sales[1]', 'nvarchar(500)'), Charge.Xchange.value('/Partner[1]/@Sales[1]', 'nvarchar(500)')) AS Xchange

我的问题是,是否有更简洁的方式来编写此查询?

2 个答案:

答案 0 :(得分:0)

在两个表上使用INNER join将省略bookid=2的行,因为cost表中没有记录。对于两个表,您可能希望使用LEFT OUTER JOIN而不是INNER JOIN来显示所有行。

那就是说,你想要的是某种中间表,它是cost / charge的组合,但只有当cost中没有记录时才会这样。

您可以执行以下操作:在其中填充包含所有cost条记录的新表格,然后填写所有charge条记录(在新表格中找不到cost )......虽然,动态创建/写入新表无疑会对性能造成影响。我不想在一个大型图书馆里这样做。

这里也是sql fiddle

create table #books (bookid int, title varchar(50), releaseyear int)
create table #charge (bookid int, charge money, publisherid int)
create table #cost  (bookid int, cost money, bookprinterid int)

insert into #books 
select 1, 'The Hobbit', 1937 union
select 2, 'Atlas Shrugged', 1957

insert into #cost
select 1, 12, 38

insert into #charge
select 1, 39, 148 union
select 2, 45, 151

create table #allcosts (bookid int, cost money)

insert into #allcosts
select c1.bookid, c1.cost from #cost c1

insert into #allcosts
select c2.bookid, c2.charge 
from #charge c2
left outer join #allcosts c3 on c2.bookid=c3.bookid
where c3.bookid is null

select b.BookID, c.cost AS Cost 
from #Books b
inner join #allcosts c on b.bookid = c.bookid

答案 1 :(得分:0)

如果Books中的所有行都不在Cost中,则无法在3个表上使用内部联接。否则,在您的示例中,将永远不会返回BookID = 2。如果要连接更多表并检索更多列,则无法使用isNull。

select bookid, isNull(cost, charge)
from Books b
inner join Charge c
on bt.bookid = c.bookid
left join Cost co
on co.bookid = bt.bookid