如何在不重复FROM / WHERE子句的情况下连接两列

时间:2014-08-27 19:51:47

标签: sql sql-server

假设我有两张表ContractsServiceProviders。合同具有引用服务提供商的属性LeadServiceProvider

我还有一个名为SubServiceProviders的第三个表,它在ContractsServiceProviders之间保持多对多关系,充当子服务提供商。

我想在Contract上运行一个查询,它会在一列中为我提供所有服务提供商的列表 - Lead和Sub:

Select 
    c.LeadServiceProvider, subSP.ServiceProvider
From 
    Contracts c 
left join 
    SubServiceProviders subSP on c.ID = subSP.Contract
Where 
    [Some contract criteria goes here]

上面的查询为我提供了两列,理想情况下,我希望将其展平为一个并运行distinct()。我可以选择LeadServiceProvider,然后UNION选择SubServiceProviders

对于这个示例来说这很简单,但是,在我的实际应用中,FROMWHERE子句非常复杂,如果我要使用UNION,我就是我不得不重复这些条款

6 个答案:

答案 0 :(得分:2)

如果您正在寻找一种在一个查询中执行此操作的简单方法,则可以使用CTE并取消列。我会用join这样明确地做到这一点:

with t as (
      Select c.LeadServiceProvider, subSP.ServiceProvider
      From Contracts c left join SubServiceProviders subSP on c.ID = subSP.Contract
      Where [Some contract criteria goes here]
     )
select distinct (case when n.n = 1 then LeadServiceProvider else ServiceProvider end) as SP
from t cross join
     (select 1 as n union all select 2) n;

编辑:

您可以轻松地将其放入子查询中:

select distinct (case when n.n = 1 then LeadServiceProvider else ServiceProvider end) as SP
from (<your query here without the order by>) t cross join
     (select 1 as n union all select 2) n;

或者忘记子查询:

  Select distinct (case when n.n = 1 then c.LeadServiceProvider
                        else subSP.ServiceProvider
                   end)
  From Contracts c left join
       SubServiceProviders subSP
       on c.ID = subSP.Contract cross join
       (select 1 as n union all select 2) n
  Where [Some contract criteria goes here]

答案 1 :(得分:0)

The query above gives me two colums that, ideally, I would flatten into
 one and run a distinct() on

如果我正确地理解你......为什么不做这样的事情。您需要将上述查询区分开来......

Select DISTINCT * from (
Select c.LeadServiceProvider, subSP.ServiceProvider
From Contracts c left join SubServiceProviders subSP on c.ID = subSP.Contract
Where [Some contract criteria goes here]) aliasname

这会给你上面的查询但只有不同的项目。 注意:尚未通过任何编辑器运行,因此我没有验证语法

答案 2 :(得分:0)

在Oracle SQL中,您始终可以使用normal with命令来消除多次使用同一个表的需要,然后将它们连接在一起

答案 3 :(得分:0)

这样的东西?

select distinct id, ServiceProvider from (
(Select distinct
    id, LeadServiceProvider as ServiceProvider, 1 as isLead, otherWhereCriteria
From 
    Contracts  ) l
union all
(Select distinct
    Contract, ServiceProvider, 0 as isLead, otherWhereCriteria
From 
    Contracts c inner join 
    SubServiceProviders s on c.ID = s.Contract) s
) u
Where
    otherWhereCriteria = targetValues

答案 4 :(得分:0)

这似乎是使用unpivot的理想时间:

SELECT DISTINCT subpvt.serviceprovider
FROM   (SELECT c.leadserviceprovider, subsp.serviceprovider, c.id
        FROM   contracts c
               LEFT JOIN subserviceproviders subsp ON c.id = subsp.contract
        WHERE  /*Some contract criteria goes here*/
                    ) p UNPIVOT (id
                        FOR serviceprovider
                        IN (leadserviceprovider, serviceprovider)) subpvt

警告:这是未经测试的,因为操作系统没有提供样本数据,我不愿意制造任何数据。

答案 5 :(得分:0)

似乎你可以在这里使用CROSS APPLY:

Select distinct
    v.ServiceProvider
From 
    Contracts c 
left join 
    SubServiceProviders subSP on c.ID = subSP.Contract
cross apply
    (values (c.LeadServiceProvider), (subSP.ServiceProvider)) as v (ServiceProvider)
Where 
    [Some contract criteria goes here]
SQL Server 2005及更高版本,SQL Server 2008及更高版本中的CROSS APPLY行构造函数支持

VALUES。您可以使用等效的UNION ALL子查询替换VALUES子句,以使查询与SQL Server 2005兼容:

(
select c.LeadServiceProvider
union all
select subSP.ServiceProvider
) as v (ServiceProvider)