[英]Select first record in a One-to-Many relation using left join
我正在尝试使用左连接来连接两个表。 结果集必须只包含“右”连接表中的第一条记录。
可以说我有两张表A和B如下;
表“A”
code | emp_no
101 | 12222
102 | 23333
103 | 34444
104 | 45555
105 | 56666
表“B”
code | city | county
101 | Glen Oaks | Queens
101 | Astoria | Queens
101 | Flushing | Queens
102 | Ridgewood | Brooklyn
103 | Bayside | New York
预期产出:
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中选择第一个匹配的记录并忽略所有其他行。
请帮忙!
谢谢
玩了一下之后,事实证明这比我想象的要复杂! 假设table_b
有一些唯一的列(例如,单字段主键),看起来你可以这样做:
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
)
;
OUTER APPLY
如果数据库支持, OUTER APPLY
是一个高效且简洁的选项。
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。
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或更高版本,则可以使用排名来实现所需。 特别是, ROW_NUMBER()
似乎很适合您的需求:
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
要么
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完美配合。
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中,您可以:
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
这是如何:
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]
嘿,如果这个城市和县是独一无二的,那就用它们吧
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)
但问题是,你必须把一些表达在那儿告诉查询处理器意味着什么,是第一个 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.