我有两张桌子需要连接在一起。但是,我只想在存在独特匹配时连接记录,而不是选择多个匹配之一进行连接。
使用 MariaDB 版本 10.3.34
核心(左)数据towns
| ID | 镇 | 邮政编码 |
|---|---|---|
| 1 | 哈德菲尔德 | HD11 4ER |
| 2 | 曼彻斯特 | MN14 3JE |
| 3 | 麦克尔斯菲尔德 | MK17 9FL |
| 4 | 爱丁堡 | ED5 3MJ |
| 5 | 利物浦 | LV9 8XT |
连接(右)数据peoples:
| ID | 名字 | 邮政编码 |
|---|---|---|
| 1 | 吉米·萨维尔 | HD11 4ER |
| 2 | 贾森·邦姆 | IP14 8FK |
| 3 | 米奇老鼠 | MK17 9FL |
| 4 | 鲍比·迪利安 | ED5 3MJ |
| 5 | 莱尼·戴维斯 | ED5 3MJ |
我最初的查询是这样的:
SELECT towns.id, towns.town, peoples.name FROM towns
LEFT JOIN people ON towns.postcode = peoples.postcode
Run Code Online (Sandbox Code Playgroud)
但这将包括Edinburgh但爱丁堡有两个人,我只想在有一个独特的排可以加入时加入。
我使用 LEFT join 因为我需要返回 的所有行,towns但仅返回唯一行peoples。
| ID | 镇 | 名字 |
|---|---|---|
| 1 | 哈德菲尔德 | 吉米·萨维尔 |
| 2 | 曼彻斯特 | <空> |
| 3 | 麦克尔斯菲尔德 | 米奇老鼠 |
| 4 | 爱丁堡 | <空> |
| 5 | 利物浦 | <空> |
我尝试过COUNT()在 JOIN 中使用但无法让它工作,
SELECT towns.id, towns.town, peoples.names FROM towns
LEFT JOIN people ON towns.postcode = peoples.postcode AND count(peoples.id) = 1
Run Code Online (Sandbox Code Playgroud)
出现语法错误。
我无法考虑如何限定此连接,它仅在找到单个结果时才连接。互联网搜索给了我很多更加模糊和偏离主题的参考资料。
我确信这很简单,但我做不到。另外,如果可能的话,我想避免子查询?
Lennart 窗口函数答案的另一种方法是仅对表使用GROUP BYandHAVING子句peoples来过滤掉具有相同内容的子句,postcode如下所示:
SELECT towns.id, towns.town, peoples.names
FROM towns
LEFT JOIN
(
SELECT MAX(names) AS names, postcode
FROM peoples
GROUP BY postcode
HAVING COUNT(name) = 1
) peoples
ON towns.postcode = peoples.postcode
Run Code Online (Sandbox Code Playgroud)
您应该能够通过以下方式加入人们:
(select name, postcode
from (
select name, postcode, count(1) over (partition by postcode) as cnt
from peoples
) as t
where cnt = 1)
Run Code Online (Sandbox Code Playgroud)
IE
SELECT t.id, t.town, p.name
FROM towns t
LEFT JOIN (SELECT name, postcode
FROM (
SELECT name, postcode
, count(1) over (partition by postcode) as cnt
FROM peoples
) as x
WHERE cnt = 1
) p
USING (postcode)
Run Code Online (Sandbox Code Playgroud)
编辑:
鉴于更新中提供的 ddl,我创建了db<>fiddle
SELECT t.id, t.town, p.names
FROM towns t
LEFT JOIN (
SELECT names, postcode
FROM (
SELECT names, postcode
, count(1) over (partition by postcode) as cnt
FROM peoples
) as x
WHERE cnt = 1
) p
USING (postcode);
Run Code Online (Sandbox Code Playgroud)
它似乎给出了预期的结果
更简单:
SELECT t.id, t.town,
IF (COUNT(DISTINCT p.names) = 1, MAX(p.names), NULL) AS names
FROM towns AS t
LEFT JOIN peoples AS p ON t.postcode = p.postcode
GROUP BY t.id
Run Code Online (Sandbox Code Playgroud)
我相信它避免了之前评论中提到的“唯一完整的分组依据”问题。(如果没有,请参阅此答案的评论。)
| 归档时间: |
|
| 查看次数: |
5739 次 |
| 最近记录: |