Sql 如何避免表联接上的无关数据
使用MSSQL 2012,我有三个表。表0有一个值,我使用该值与其他一些表连接,如下所示:Sql 如何避免表联接上的无关数据,sql,sql-server,Sql,Sql Server,使用MSSQL 2012,我有三个表。表0有一个值,我使用该值与其他一些表连接,如下所示: Table0 ---------- keyval 1 Table1 ---------- keyval someval 1 blah 1 blah1 Table2 ---------- keyval someotherval 1 woo 1 woo1 1 woo2 现在,如果我执行以下查询 SELECT Table1
Table0
----------
keyval
1
Table1
----------
keyval someval
1 blah
1 blah1
Table2
----------
keyval someotherval
1 woo
1 woo1
1 woo2
现在,如果我执行以下查询
SELECT Table1.someval AS val1, Table2.someotherval AS val2
FROM Table0
INNER JOIN Table1 ON Table0.keyval = Table1.keyval
INNER JOIN Table2 ON Table0.keyval = Table2.keyval
WHERE Table0.keyval = '1'
我得到以下结果:
val1 val2
----------
blah woo
blah woo1
blah woo2
blah1 woo
blah1 woo1
blah1 woo2
我的问题是,如何确保每个值在结果中只显示一次?我想知道如何运行查询以获得以下结果
val1 val2
----------
blah woo
blah1 woo1
null woo2
我尝试过各种各样的连接,但没有好结果。我有一种感觉,我需要在某个地方使用UNION,但我不确定在哪里如果您希望看到来自联接表的空结果,请使用“左联接”
SELECT Table1.someval AS val1, Table2.someotherval AS val2
FROM Table0
LEFT JOIN Table1 ON Table0.keyval = Table1.keyval
LEFT JOIN Table2 ON Table0.keyval = Table2.keyval
WHERE Table0.keyval = '1'
我有一种感觉,将唯一值拉到一列中会容易得多, 然后使用第二个“dummy”列指定值的来源。 因为他们不一定要配对,所以没有理由把他们成对地列出来
SELECT DISTINCT Table1.someval AS val,'Table1' As source
FROM Table1
WHERE Table1.keyval = '1'
UNION
SELECT DISTINCT Table2.someval as val, 'Table2' As source
FROM Table2
WHERE Table2.keyval = '1'
注意,在本例中,我完全删除了Table0,数据的设置方式与您的问题相同,Table0唯一重要的时间是如果Table0中没有keyval=1,那么您将不会得到任何结果
但是,如果这对你很重要
SELECT DISTINCT Table1.someval AS val,'Table1' As source
FROM Table1
INNER JOIN Table0 ON Table0.keyval = Table1.keyval
WHERE Table0.keyval = '1'
UNION
SELECT DISTINCT Table2.someval as val, 'Table2' As source
FROM Table2
INNER JOIN Table0 ON Table0.keyval = Table2.keyval
WHERE Table0.keyval = '1'
您似乎想要笛卡尔乘积的一个随机子集,其中每个值都表示一次,因此类似这样的操作应该可以:
with t0(k) as (
select 1
), t1(k,v1) as (
select 1,'blah'
union
select 1,'blah1'
), t2(k,v2) as (
select 1,'woo'
union
select 1,'woo1'
union
select 1,'woo2'
), t3(k,v1,rn) as (
select t1.k, v1, row_number() over (order by t1.v1) as rn1
from t1
join t0
on t0.k = t1.k
), t4(k,v2,rn) as (
select t2.k, v2, row_number() over (order by t2.v2) as rn2
from t2
join t0
on t0.k = t2.k
)
select t3.v1, t4.v2
from t3
full join t4
on t3.k = t4.k
and t3.rn = t4.rn
V1 V2
blah woo
blah1 woo1
(null) woo2
编辑:使用表格代替CTE t0、t1和t2
create table table0 (k int not null);
insert into table0 (k) select 1;
create table table1 (k int not null, v1 varchar(5) not null);
create table table2 (k int not null, v2 varchar(5) not null);
insert into table1 (k,v1)
select 1,'blah'
union
select 1,'blah1'
union
select 1, 'jojo'
union
select 1, 'jojo1';
insert into table2 (k,v2)
select 1,'woo'
union
select 1,'woo1'
union
select 1,'woo2';
with t3(k,v1,rn) as (
select t1.k, v1, row_number() over (order by t1.v1) as rn1
from table1 t1
join table0 t0
on t0.k = t1.k
), t4(k,v2,rn) as (
select t2.k, v2, row_number() over (order by t2.v2) as rn2
from table2 t2
join table0 t0
on t0.k = t2.k
)
select t3.v1, t4.v2
from t3
full join t4
on t3.k = t4.k
and t3.rn = t4.rn;
V1 V2
blah woo
blah1 woo1
jojo woo2
jojo1 (null)
delete from table1 where v1 like 'joj%';
with t3(k,v1,rn) as (
select t1.k, v1, row_number() over (order by t1.v1) as rn1
from table1 t1
join table0 t0
on t0.k = t1.k
), t4(k,v2,rn) as (
select t2.k, v2, row_number() over (order by t2.v2) as rn2
from table2 t2
join table0 t0
on t0.k = t2.k
)
select t3.v1, t4.v2
from t3
full join t4
on t3.k = t4.k
and t3.rn = t4.rn;
V1 V2
blah woo
blah1 woo1
(null) woo2
根据给定的数据,我得到的距离为:
select s.val1, s.val2
from (
select t1.someval as val1
, null as val2
from table1 t1
union
select null as val1
, t2.someotherval as val2
from table2 t2
) s
结果是:
val1 | val2
--------------
blah | (null)
blah1 | (null)
(null)| woo
(null)| woo1
(null)| woo2
看
否则,您可以实现以下目标:
val
-------
blah
blah1
woo
woo1
woo2
使用此查询:
select t1.someval as val
from table1 t1
union
select t2.someotherval
from table2 t2
看
虽然这两个结果集都不是所需的结果集,但这是我能从给定输入中得到的最接近的结果集。查询如何知道blah与woo匹配而不是与woo1匹配?您需要添加列,以便在数据库中明确关系。。。因为所有的keyval都是一样的,这就是预期的行为……您是否只是尝试在val的最后一个字符上进行联接?似乎您希望查询找出返回的列中哪一个具有最明显的值(在本例中为val2),然后将val2的每个值与满足联接条件的任何尚未使用的val1值进行匹配,如果val1的所有值都已用尽,则可能使用null。本例中的SELECT DISTINCT将获取所有6行,因为每行中的值组合都是DISTINCTGIVEND DATA不适合所需的结果集。您需要一个额外的键来匹配特定于表1和表2关系的记录。否则,我看不出你如何能达到预期的结果。通常,当一个表中的数据与另一个表中的数据没有可能的相关性时,就会得到这样的结果集,因此会出现空值。您希望在哪里找到空值?表0、表1或表2?查看您提供的表中的数据,不会有空值,因为每个键都会找到一个匹配的Table0.keyval、Table1.keyval、Table2.keyval。是的,我一直认为这可能也是最好的方法。我将等待一点,看看是否有sql忍者有一些偷偷摸摸的解决方案在这里;否则我会把这个标记为answer@Lennart:您是否正在从db中提取数据?t0、t1和t2模拟了其queryhaha中的表不,我在web服务中使用的参数化存储过程中已经有了这些数据。它工作得很好,因为通过将参数和我需要的主表中的所有列放在t0中,我能够获得所有相关数据,而无需复制每行中的所有数据。此外,返回的最大行数等于其中一个“副表”中的最大行数。我有很多这样的“副表”,所以这为我节省了大量通过网络发送的数据。值得注意的是,使用CTE不会允许将其转换为MySQL解决方案,如果您必须使用MySQL中的数据复制此工作流,这可能不相关,但值得注意。此外,如果val1现在有这些值:blah,blah1,blah2,blah3,这个答案会发生什么变化。。。OP表示,在这个原因中,val2需要空值。这似乎需要大量的代码修改,您需要手动了解列的唯一条目,以及哪些列的基数最大。这使得可重用性差。