SQL Join忽略多个匹配(模糊结果ok)

时间:2010-06-29 18:42:12

标签: sql tsql

我甚至不知道我的问题叫什么名字,所以我只想提供一些样本数据。我不介意模糊的结果(这是我能想到表达它的最佳方式。我不介意我忽略一些数据,这是为了近似的评估,而不是详细的会计,如果这是有道理的)。但我确实需要表1中的每条记录,我想避免下面指出的空值。

这是可能的吗?

TABLE 1
acctnum sub fname  lname  phone
 12345   1   john   doe   xxx-xxx-xxxx
 12346   0   jane   doe   xxx-xxx-xxxx
 12347   0   rob    roy   xxx-xxx-xxxx
 12348   0   paul  smith  xxx-xxx-xxxx

TABLE 2
acctnum sub division
 12345   1   EAST
 12345   2   WEST
 12345   3   NORTH
 12346   1   TOP
 12346   2   BOTTOM
 12347   2   BALLOON
 12348   1   NORTH

因此,如果我们进行“常规外部”连接,我们会得到一些这样的结果,因为子0与第二个表不匹配:

TABLE AFTER JOIN
acctnum sub fname  lname  phone         division
 12345   1   john   doe   xxx-xxx-xxxx   EAST
 12346   0   jane   doe   xxx-xxx-xxxx   null
 12347   0   rob    roy   xxx-xxx-xxxx   null
 12348   0   paul  smith  xxx-xxx-xxxx   null

但我宁愿得到

TABLE AFTER JOIN
acctnum sub fname  lname  phone         division
 12345   1   john   doe   xxx-xxx-xxxx   EAST
 12346   0   jane   doe   xxx-xxx-xxxx   TOP
 12347   0   rob    roy   xxx-xxx-xxxx   BALLOON
 12348   0   paul  smith  xxx-xxx-xxxx   NORTH

我正试图避免:

TABLE AFTER JOIN
acctnum sub fname  lname  phone         division
 12345   1   john   doe   xxx-xxx-xxxx   EAST
 12345   1   john   doe   xxx-xxx-xxxx   WEST
 12345   1   john   doe   xxx-xxx-xxxx   NORTH
 12346   0   jane   doe   xxx-xxx-xxxx   TOP
 12346   0   jane   doe   xxx-xxx-xxxx   BOTTOM
 12347   0   rob    roy   xxx-xxx-xxxx   BALOON
 12348   0   paul  smith  xxx-xxx-xxxx   NORTH

所以我决定使用工会和两个if条件。对于表1中定义的子帐户但在表2中没有定义的情况,我会接受null,对于其他所有情况,我只会匹配min。

4 个答案:

答案 0 :(得分:3)

如果我理解正确,看起来您正试图加入sub列,如果匹配的话。如果sub上没有匹配项,那么您希望它为acctnum选择“第一”行。这是对的吗?

如果是这样,您需要在完全匹配时离开联接,然后在select语句上执行另一个左连接,该语句确定与最低division值对应的sub那个acctnumrow_number()函数可以帮助您完成此操作,如下所示:

select
    t1.acctnum, 
    t1.sub, 
    t1.fname, 
    t1.lname, 
    t1.phone, 
    isnull(t2_match.division, t2_first.division) as division

from table1 t1

left join table2 t2_match on t2_match.acctnum = t1.acctnum and t2_match.sub = t1.sub
left join 
(
    select 
        acctnum, 
        sub, 
        division,
        row_number() over (partition by acctnum order by sub) as rownum

    from table2
) t2_first on t2_first.acctnum = t1.acctnum

修改

如果您根本不关心哪个记录,当匹配的sub不存在时从表2中返回,您可以组合两个不同的查询(一个匹配sub和一个只需要使用union进行最小或最大分割。

select
    t1.acctnum, 
    t1.sub, 
    t1.fname, 
    t1.lname, 
    t1.phone, 
    t2.division

from table1 t1

join table2 t2 on t2.acctnum = t1.acctnum and t2.sub = t1.sub

union

select
    t1.acctnum, 
    t1.sub, 
    t1.fname, 
    t1.lname, 
    t1.phone, 
    min(t2.division)

from table1 t1

join table2 t2 on t2.acctnum = t1.acctnum
left join table2 t2_match on t2_match.acctnum = t1.acctnum and t2_match.sub = t1.sub

where t2_match.acctnum is null

就个人而言,我没有发现union语法更加引人注目,您现在必须在两个地方维护查询。出于这个原因,我赞成row_number()方法。

答案 1 :(得分:2)

尝试使用

SELECT     MIN(Table_1.acctnum) as acctnum , MIN(Table_1.sub) as sub,MIN( Table_1.fname) as fname, MIN(Table_1.lname) as name, MIN(Table_1.phone) as phone, MIN(Table_2.division) as division 
FROM Table_1 INNER JOIN   Table_2 ON Table_1.acctnum = Table_2.acctnum AND Table_1.sub = Table_2.sub
where Table_1.sub>0
group by Table_1.acctnum 
union 
SELECT     MIN(Table_1.acctnum) as acctnum , MIN(Table_1.sub) as sub,MIN( Table_1.fname) as fname, MIN(Table_1.lname) as name, MIN(Table_1.phone) as phone, MIN(Table_2.division) as division 
FROM Table_1 INNER JOIN   Table_2 ON Table_1.acctnum = Table_2.acctnum 
where Table_1.sub=0
group by Table_1.acctnum

这是结果

12345   1   john        doe         xxxxxxxxxx  EAST      
12346   0   jane        doe         xxxxxxxxxx  BOTTOM    
12347   0   rob         roy         xxxxxxxxxx  BALLOON   
12348   0   paul        smith       xxxxxxxxxx  NORTH  

如果你将min改为max,那么第二行将会出现BOTTOM

答案 2 :(得分:1)

这将准确地给出您想要的结果(对于显示的数据):

已更新以假设始终存在sub == 1值:

SELECT
    T1.acctnum,
    T1.sub,
    T1.fname,
    T1.lname,
    T1.phone,
    T2.division
FROM
    TABLE_1 T1
LEFT JOIN
    TABLE_2 T2  ON T1.acctnum = T2.acctnum
AND
    T2.sub  = (SELECT MIN(T3.sub) FROM TABLE_2 T3  WHERE T1.acctnum = T3.acctnum)
ORDER BY
    T1.lname,
    T1.fname,
    T1.acctnum

答案 3 :(得分:1)

它也可能对您有用:

SELECT  t1.acctnum, t1.sub, t1.fname, t1.lname, t1.phone, 
ISNULL(MAX(t2.division),MAX(t3.division)) as division
FROM table_1 t1
LEFT JOIN table_2 t2 ON (t2.acctnum = t1.acctnum AND t1.sub = t2.sub)
LEFT JOIN table_2 t3 ON (t3.acctnum = t1.acctnum)
GROUP BY  t1.acctnum, t1.sub, t1.fname, t1.lname, t1.phone