sql中的union之间的where子句?

时间:2019-01-16 22:59:14

标签: sql sql-server

我有一个查询,该查询通过使用Union条件垂直扩展数据。以下是2个示例表:

create table #temp1(_row_ord int,CID int,_data varchar(10))

insert #temp1
values
(1,1001,'text1'),
(2,1001,'text2'),
(4,1002,'text1'),
(5,1002,'text2')


create table #temp2(_row_ord int,CID int,_data varchar(10))
insert #temp2
values
(1,1001,'sample1'),
(2,1001,'sample2'),
(4,1002,'sample1'),
(5,1002,'sample2')

--My query
select * from #temp1 
union
select * from #temp2 where CID in (select CID from #temp1)
order by _row_ord,CID

drop table #temp1,#temp2

所以我当前的输出是:

enter image description here

我想将无法在Union条件中使用'where'子句的每个客户的详细信息归为一组。

我想要的输出:

enter image description here

有帮助吗?!排序依据也无济于事。

4 个答案:

答案 0 :(得分:3)

我可以想象您想要一个CID的所有行,它们从第一个表开始按_row_ord排序,然后是第二个表的所有行。并且CID应该是最外面的排序标准。

如果正确,则可以从表中选择文字。让第一个表的文字小于第二个表的文字。然后首先按CID排序,然后按原义排序,最后按_row_ord排序。

SELECT cid,
       _data
       FROM (SELECT 1 s,
                    _row_ord,
                    cid,
                    _data
                    FROM #temp1
             UNION ALL
             SELECT 2 s,
                    _row_ord,
                    cid,
                    _data
                    FROM #temp2) x
       ORDER BY cid,
                s,
                _row_ord;

db<>fiddle

答案 1 :(得分:0)

如果我正确理解您的需求,则需要对输出进行排序,以使每个#temp1值的#temp2行出现在cid行之前。

您可以做的是生成另一个列ordnum,为每个表分配值(仅出于排序目的),然后在外部select语句中删除它。

select cid, _data
from (
  select 1 as ordnum, * 
  from #temp1 
  union all
  select 2 as ordnum, * 
  from #temp2 t2
  where exists (
    select 1
    from #temp1 t1
    where t1.cid = t2.cid
    )
  ) q
order by cid, ordnum

我还用where运算符将您的exists条件重写为等效条件,

Live DEMO - click me!

输出

cid     _data
1001    text1
1001    text2
1001    sample1
1001    sample2
1002    text1
1002    text2
1002    sample1
1002    sample2

答案 2 :(得分:0)

用于。这是我第一次尝试使用您的sql

create table #temp1(_row_ord int,CID int,_data varchar(10))

insert #temp1
values
(1,1001,'text1'),
(2,1001,'text2'),
(4,1002,'text1'),
(5,1002,'text2')


create table #temp2(_row_ord int,CID int,_data varchar(10))
insert #temp2
values
(1,1001,'sample1'),
(2,1001,'sample2'),
(4,1002,'sample1'),
(5,1002,'sample2');

WITH result( _row_ord, CID,_data) AS
(
--My query
select * from #temp1 
union
select * from #temp2 where CID in (select CID from #temp1)


)
select * from tmp order by CID ,_data
drop table #temp1,#temp2

结果

_row_ord    CID _data
1   1001    sample1
2   1001    sample2
1   1001    text1
2   1001    text2
4   1002    sample1
5   1002    sample2
4   1002    text1
5   1002    text2

答案 3 :(得分:-1)

联合放在两个结果集块之间,并形成一个结果集块。如果要在特定块上使用where子句,可以将其放在其中:

select a from a where a = 1
union
select z from z


select a from a
union
select z from z where z = 1


select a from a where a = 1
union
select z from z where z = 1

联合中的第一个查询在输出中定义列名称。您可以将输出包装在方括号中,对其进行别名处理,然后在整个批次中放置一个位置:

select * from
(
  select a as newname from a where a = 1
  union
  select z from z where z = 2
) o
where o.newname = 3

重要的是要注意a.a和z.z将合并为一个新列,即o.newname。结果,说where o.newname将对a和z的所有行进行过滤(z的行也被堆叠到newname列中)。外部查询只知道o.newname,不知道a或z

请注意,上面的查询不会产生任何结果,因为我们知道联合仅将a.a为1和z.z为2的行输出为o.newname。然后,将这个o.newname过滤为仅输出3的行,但没有3的行。

select * from
(
  select a as newname from a
  union
  select z from z
) o
where o.newname = 3

由于过滤了结果并集,因此该查询将选择a.a为3或z.z为3的a或z中的任何行