[英]Better way to joining tables to pick data from one or other table
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
That's the book publishing tables data I have. 那就是我拥有的图书出版表格数据。
Books table, Cost table and Charge table. 帐簿表,成本表和费用表。
I would like to see cost information if present else charge data from single query. 我想查看成本信息(如果存在),否则会从单个查询中收取费用数据。 ie
即
BookID Cost
1 12
2 45
This is my query 这是我的查询
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
That works, but problem is if there are more tables to join or more columns to retrieve, having ISNULL condition for every column will become a big blob of text, especially if you have to parse xml. 那行得通,但是问题是,如果要连接更多表或要检索更多列,则每列具有ISNULL条件将成为一大堆文本,尤其是在必须解析xml时。
ISNULL(Cost.Xchange.value('/Partner[1]/@Sales[1]', 'nvarchar(500)'), Charge.Xchange.value('/Partner[1]/@Sales[1]', 'nvarchar(500)')) AS Xchange
My question is, is there a neater way to write this query? 我的问题是,有没有更整洁的方式编写此查询?
Using an INNER join
on both tables, will omit the row for bookid=2
as there is no record in the cost
table for it. 在两个表上都使用
INNER join
bookid=2
,将省略bookid=2
的行,因为它在cost
表中没有记录。 You likely want to use LEFT OUTER JOIN
instead of INNER JOIN
for both tables to show all rows. 您可能想对两个表使用
LEFT OUTER JOIN
而不是INNER JOIN
来显示所有行。
That said, what you want is some sort of intermediate table that is a combination of cost
/ charge
but only when there is no record in cost
. 就是说,您想要的是某种中间表,该中间表是
cost
/ charge
的组合,但仅当没有cost
记录时cost
。
You could do something like this, where you populate a new table with all the cost
records, and then all the charge
records (where no cost
is found in the new table)... Although, there would undoubtedly be a performance hit by creating/writing to a new table on the fly. 您可以执行类似的操作,在该表中先填充所有
cost
记录,然后填充所有charge
记录(在新表中未找到cost
)...虽然,无疑会因创建/动态地写入新表。 I wouldn't want to do this in a large library. 我不想在大型图书馆中这样做。
Here's a sql fiddle too. 这也是一个SQL提琴 。
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
If all rows in Books are not in Cost you can't use inner joins on the 3 tables. 如果“书籍”中的所有行均不在“成本”中,则不能在这3个表上使用内部联接。 Otherwise in your example BookID=2 will never be returned.
否则,在您的示例BookID = 2中将永远不会返回。 There is no way around using isNull if you are going to join more tables and retrieve more columns.
如果要联接更多表并检索更多列,则无法使用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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.