【问题标题】:Better way to joining tables to pick data from one or other table连接表以从一个或其他表中选择数据的更好方法
【发布时间】:2014-06-10 20:58:22
【问题描述】:
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

我的问题是,有没有更简洁的方法来编写这个查询?

【问题讨论】:

  • 我会给出最短的答案——不!您如何期望在不实际执行的情况下查询某些内容?您仅在必要时使用功能。有些列永远不会为空。您可以使用where Cost.Cost is not null 限制您的数据输出,并且您的数据永远不会为空。但是,是的,你必须写东西

标签: sql sql-server join


【解决方案1】:

在两个表上使用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

【讨论】:

  • 我应该使用临时表吗?这比我的情况还要糟糕。
  • 不,您不必使用临时表,这只是为了演示目的。但是,如果这是您选择的路线,则可以轻松地即时索引临时表。我完全同意,它的性能可能比您当前的解决方案差。
【解决方案2】:

如果 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

【讨论】:

  • 对不起,我的错。我已经离开了那里。我的问题是,有没有更好的方法来编写上述查询,而不是在这么多列上执行 isnull 。基本上是在找一个更短的版本,希望它会更整洁。
猜你喜欢
  • 2021-08-22
  • 2020-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-24
  • 2015-02-20
相关资源
最近更新 更多