Select first record in a One-to-Many relation using left join
我正在尝试使用左连接来连接两个表。 结果集必须只包含"右"连接表中的第一条记录。
可以说我有两张表A和B如下;
表"A"
1 2 3 4 5 6 7 | code | emp_no 101 | 12222 102 | 23333 103 | 34444 104 | 45555 105 | 56666 |
表"B"
1 2 3 4 5 6 | code | city | county 101 | Glen Oaks | Queens 101 | Astoria | Queens 101 | Flushing | Queens 102 | Ridgewood | Brooklyn 103 | Bayside | NEW York |
预期产出:
1 2 3 4 5 6 | code | emp_no | city | county 101 | 12222 | Glen Oaks | Queens 102 | 23333 | Ridgewood | Brooklyn 103 | 34444 | Bayside | NEW York 104 | 45555 | NULL | NULL 105 | 56666 | NULL | NULL |
如果你注意到我的结果在左连接之后只有表"B"中的一个匹配记录(无论匹配什么记录)(并且它是一对多的映射)
我需要从表B中选择第一个匹配的记录并忽略所有其他行。
请帮忙!
谢谢
玩了一下之后,事实证明这比我想象的要复杂!假设
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | SELECT table_a.code, table_a.emp_no, table_b.city, table_b.county FROM table_a LEFT JOIN table_b ON table_b.code = table_a.code AND table_b.field_that_is_unique = ( SELECT TOP 1 field_that_is_unique FROM table_b WHERE table_b.code = table_a.code ) ; |
另一种选择:
如果数据库支持,
1 2 3 4 5 6 7 8 9 | SELECT * FROM Table_A a OUTER APPLY (SELECT TOP 1 * FROM Table_B b_1 WHERE b_1.code = a.code ) b ; |
这导致左连接到不确定的第一匹配记录。我的测试显示它比任何其他发布的解决方案更快(在MS SQL Server 2012上)。
最高投票的答案对我来说似乎不正确,而且似乎过于复杂。
只需按子查询中表B上的代码字段进行分组,然后选择每个分组的最大Id。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | SELECT table_a.code, table_a.emp_no, table_b.city, table_b.county FROM table_a LEFT JOIN table_b ON table_b.code = table_a.code AND table_b.field_that_is_unique IN (SELECT MAX(field_that_is_unique) FROM table_b GROUP BY table_b.code) |
如果您使用的是SQL Server 2005或更高版本,则可以使用排名来实现所需。特别是,
1 2 3 4 5 6 7 8 9 10 11 12 13 | WITH B_ranked AS ( SELECT *, rnk = ROW_NUMBER() OVER (PARTITION BY code ORDER BY city) FROM B ) SELECT A.code, A.emp_no, B.city, B.county FROM A LEFT JOIN B_ranked AS B ON A.code = B.code AND b.rnk = 1 |
要么
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | WITH B_unique_code AS ( SELECT * FROM( SELECT *, rnk = ROW_NUMBER() OVER (PARTITION BY code ORDER BY city) FROM B ) AS s WHERE rnk = 1 ) SELECT A.code, A.emp_no, B.city, B.county FROM A LEFT JOIN B_unique_code AS B ON A.code = B.code |
我修改了ruakh的答案,这似乎与mysql完美配合。
1 2 3 4 5 6 7 8 9 10 11 12 13 | SELECT table_a.code, table_a.emp_no, table_b.city, table_b.county FROM table_a a LEFT JOIN table_b b ON b.code = a.code AND b.id = ( SELECT id FROM table_b WHERE table_b.code = table_a.code LIMIT 1 ) ; |
在Oracle中,您可以:
1 2 3 4 5 6 7 | WITH first_b AS (SELECT code, MIN(rowid) AS rid FROM b GROUP BY code)) SELECT a.code, a.emp_no, b.city, b.county FROM a INNER JOIN first_b ON first_b.code = a.code INNER JOIN b ON b.rowid = first_b.rid |
这是如何:
1 2 3 4 | SELECT * FROM TableA a LEFT JOIN TableB b ON b.Code = a.Code AND [Here put criteria predicate that 'defines' what the FIRST record IS] |
嘿,如果这个城市和县是独一无二的,那就用它们吧
1 2 3 4 5 6 7 | SELECT * FROM TableA a LEFT JOIN TableB b ON b.Code = a.Code AND b.City + b.county = (SELECT MIN(city + county) FROM TableB WHERE Code = b.Code) |
但重点是你必须在那里放一些表达来告诉查询处理器首先意味着什么。