将两个查询结果合并为一个具有SQL Server条件的查询结果

时间:2018-03-06 15:31:13

标签: sql sql-server

我有两个查询将两个结果合并为一个。然而;我的挑战是如果在第一个查询中不存在第二个查询,请查看第一个查询。

我将帖子更改为实际查询

   SELECT        Name.CO_ID, Name.FULL_NAME, Name.ID, rpt.date AS StartDate, 
                     vw_Coords.TARGET_ID AS CoordID, vw_RegDirs.TARGET_ID AS 
   RDID
   FROM            Name INNER JOIN
                     Tops_Profile ON dbo.Name.ID = Tops_Profile.ID left 
   outer JOIN
                     vw_mz_rpt_leader_log rpt ON Name.CO_ID = rpt.ID LEFT 
   OUTER JOIN
                     vw_RegDirs ON Name.CO_ID = vw_RegDirs.CHAPTER LEFT 
   OUTER JOIN
                     vw_Coords ON Name.CO_ID = vw_Coords.CHAPTER LEFT OUTER 
   JOIN
                     Tops_Chapter ON Tops_Chapter.ID = Name.CO_ID
   WHERE        (Name.MEMBER_TYPE = 'm') AND (Tops_Profile.LDR = '1') and 
   LOG_TEXT like '%LEADER Change%'

   union 

   SELECT        Name.CO_ID, Name.FULL_NAME, Name.ID, 
   YEAR(dbo.Tops_Chapter.PST_DATE_LEAD) AS StartDate, 
                     vw_Coords.TARGET_ID AS CoordID, vw_RegDirs.TARGET_ID AS 
   RDID
   FROM            Name INNER JOIN
                     Tops_Profile ON Name.ID = Tops_Profile.ID left outer 
   JOIN
                     vw_mz_rpt_leader_log rpt ON Name.CO_ID = rpt.ID LEFT 
   OUTER JOIN
                     vw_RegDirs ON Name.CO_ID = vw_RegDirs.CHAPTER LEFT 
   OUTER JOIN
                     vw_Coords ON Name.CO_ID = vw_Coords.CHAPTER LEFT OUTER 
   JOIN
                     Tops_Chapter ON Tops_Chapter.ID = Name.CO_ID
   WHERE        (Name.MEMBER_TYPE = 'm') AND (Tops_Profile.LDR = '1')

范围是如果第一个查询中存在记录,则不从第二个查询中引入它。

7 个答案:

答案 0 :(得分:1)

这是一种快速而又肮脏的方式......

select *
from
(select id, Name, log.Date 
from Name
inner join Log on Name.id = log.id
where log.text_log like '%Leader%'
union
select id, Name, Profile.Date 
from Name
inner join profile on Name.id = profile.id
where profile.Leader = '1') d
order by row_number() over(partition by x.id order by x.Date asc)

请注意,这并不关心John来自何处,它只是根据您想要的日期找到第一次出现。

答案 1 :(得分:0)

使用row_number并选择日期最短的ID

with cte as
(select id, Name, log.Date 
from Name
inner join Log on Name.id = log.id
where log.text_log like '%Leader%'
union all
select id, Name, Profile.Date as log.date
from Name
inner join profile on Name.id = profile.id
where profile.Leader = '1' 
) , ct1 as (select id,name,log.date, ROW_NUMBER() over (partition by id order by log.date) rn from cte )

select id,name,log.date from ct1 where rn = 1

答案 2 :(得分:0)

where profile.Leader = '1'  
  and id not in ( select Name.id
                  from Name
                  inner join Log 
                     on Name.id = log.id
                  where log.text_log like '%Leader%' )

答案 3 :(得分:0)

您可以在第二个查询中使用NOT EXISTS来过滤掉现有的Name记录:

select id, Name, log.Date 
from Name
inner join Log on Name.id = log.id
where log.text_log like '%Leader%'

union

select n1.id, n1.Name, Profile.Date 
from Name as n1
inner join profile on n1.id = profile.id
where profile.Leader = '1' and 
      not exists (select 1
                  from Name as n2
                  inner join Log on n2.id = Log.id
                  where Log.text_log like '%Leader%' and 
                        n2.id = n1.id and n2.name = n1.name)

答案 4 :(得分:0)

下面的查询查找每个名称的logdate和profiledate。如果有logdate,则会显示日期,否则将显示配置文件日期。如果两者都不存在,则不会显示名称。

select id, Name, coalesce(log.Date,profile.date)
from Name
left join Log on Name.id = log.id and log.text_log like '%Leader%'
left join profile on Name.id = profile.id and profile.Leader = '1'
where coalesce(log.Date,profile.date) is not null

答案 5 :(得分:0)

您可以为两个查询添加排名。然后根据ID,您可以保持记录具有更好的排名(使用TOP (1) WITH TIESselect top(1) with ties id, name, date from ( select n.id, n.name, log.date, 1 as rnk from name n inner join log on name.id = log.id where log.text_log like '%Leader%' union all select n.id, n.name, profile.date, 2 as rnk from name n inner join profile on name.id = profile.id where profile.leader = '1' ) data order by rank() over (partition by id order by rnk); )。

{{1}}

答案 6 :(得分:0)

您已更改了您的请求。突然,两个查询都从相同的表中进行选择,而UNION(或UNION ALL就此而言)似乎不再是一个好的解决方案。

两个查询之间的差异很小。从整体来看,它归结为:为member_type = 'm' and tp.ldr = 1选择记录,然后每个名称只保留一条记录,最好是log_text like '%LEADER Change%'。这仅仅是排名,正如我在其他答案中所示。您只需要一个查询来选择相关的所有记录,并使用TOP (1) WITH TIES来保持每个名称的最佳匹配。

select top(1) with ties
  n.co_id,
  n.full_name,
  n.id,
  case when log_text like '%LEADER Change%' then rpt.date else year(tc.pst_date_lead) end
    as startdate,
  c.target_id as coordid,
  rd.target_id as rdid
from name n
inner join tops_profile tp on n.id = tp.id
left outer join vw_mz_rpt_leader_log rpt on n.co_id = rpt.id
left outer join vw_regdirs rd on n.co_id = rd.chapter
left outer join vw_coords c on n.co_id = c.chapter
left outer join tops_chapter tc on tc.id = n.co_id
where n.member_type = 'm'
  and tp.ldr = 1
order by row_number() over (
             partition by n.id
             order by case when log_text like '%LEADER Change%' then 1 else 2 end);

正如你所说,你只希望每个名字只有一条记录,我正在使用ROW_NUMBER。如果您想要更多,请改用RANK

目前尚不清楚为什么要加入tops_chapter表。 log_text是该表中的一列吗? (您应该在查询中为此列使用表限定符。)如果不是,则连接是多余的,您可以从查询中删除它。