获取此结果集的其他方法有哪些

时间:2015-11-07 04:24:29

标签: sql-server

获得相同结果集的其他方法有哪些

我正在使用4张桌子

SELECT * FROM Terminal
SELECT * FROM Customer
SELECT * FROM Contract
SELECT * FROM ExternalTable

这4个表格中的数据如下:

enter image description here

我写的查询是

    select ex.TerminalName,ex.CustomerName from ExternalTable ex
except
select t.TerminalName,ct.CustomerName from [Contract] c
inner join Terminal t on t.TerminalID=c.TerminalID
inner join Customer ct on ct.CustomerId=c.CustomerId

获得以下结果

enter image description here

所以只是想知道获得同样结果的其他方法是什么

3 个答案:

答案 0 :(得分:1)

我并不是你想要的,但是这是另一种编写应该产生相同结果的查询的方法:

SELECT 
    ex.TerminalName,
    ex.CustomerName 
FROM 
    ExternalTable ex
WHERE
    NOT EXISTS( SELECT
                    NULL
                FROM        
                    [Contract] c
                INNER JOIN 
                    Terminal t on t.TerminalID = c.TerminalID
                INNER JOIN 
                    Customer ct on ct.CustomerId = c.CustomerId
                WHERE
                    t.TerminalName = ex.TerminalName
                AND
                    ex.CustomerName = ct.CustomerName
                )

答案 1 :(得分:1)

这应该是等同的:

select ex.TerminalName,ex.CustomerName
from
    ExternalTable ex
    left outer join
    (
        [Contract] c
        inner join Terminal t
            on t.TerminalID=c.TerminalID
        inner join Customer ct
            on ct.CustomerId=c.CustomerId
    )
        on ex.TerminalName = t.TerminalName and ex.CustomerName = ct.CustomerName
where t.TerminalName is null and ct.CustomerName is null

您应该注意except返回不同的结果,并且严格相同,我需要指定select distinct

答案 2 :(得分:1)

这是一个自包含的示例,显示了两个替代方案。 一个使用NOT IN,另一个使用LEFT OUTER JOIN,但它们应该是等效的。

--set up temp tables with dummy data to replicate the issue

declare @Terminal table(terminalid int,terminalname nvarchar(100));
insert into @Terminal select 1,'Terminal1' union select 2,'Terminal2'

declare @Customer table(customerid int,customername nvarchar(100));
insert into @Customer select 1,'Customer1' union select 2,'Customer2';

declare @Contract table(contractid int,terminalid int,customerid int,contractname nvarchar(100));
insert into @Contract select 1,1,1,'Contract1';

declare @ExternalTable table(externalid int,terminalname nvarchar(100),customername nvarchar(100),contractname nvarchar(100));
insert into @ExternalTable select 1,'Terminal1','Customer1','Contract1' union select 2,'Terminal2','Customer1','Contract1'

--SELECT * FROM @Terminal
--SELECT * FROM @Customer
--SELECT * FROM @Contract
--SELECT * FROM @ExternalTable

--goal: show records that are in the external table, but are not fully linked in the other tables

--original
select ex.TerminalName,ex.CustomerName from @ExternalTable ex
except
select t.TerminalName,ct.CustomerName from @Contract c
inner join @Terminal t on t.TerminalID=c.TerminalID
inner join @Customer ct on ct.CustomerId=c.CustomerId

--revised (left outer join method)
select et.TerminalName,et.CustomerName
from
  @ExternalTable et
  left join (
    select ex.externalid
    from
      @Contract c
      inner join @Terminal t on t.TerminalID=c.TerminalID
      inner join @Customer ct on ct.CustomerId=c.CustomerId
      inner join @ExternalTable ex on ex.terminalname = t.terminalname and ex.customername = ct.customername
  ) excludes on excludes.externalid = et.externalid
where excludes.externalid is null

--revised ("not in" method)
select et.TerminalName,et.CustomerName
from
  @ExternalTable et
where et.externalid not in(
  select ex.externalid
  from
    @Contract c
    inner join @Terminal t on t.TerminalID=c.TerminalID
    inner join @Customer ct on ct.CustomerId=c.CustomerId
    inner join @ExternalTable ex on ex.terminalname = t.terminalname and ex.customername = ct.customername
  )