gpt4 book ai didi

当 WHERE 不匹配时返回具有特定 NULL 值的记录的 SQL 查询

转载 作者:行者123 更新时间:2023-11-29 14:32:18 24 4
gpt4 key购买 nike

我在 Postgres 中运行以下查询:

SELECT  raw_times.*, efforts.id as effort_id, efforts.event_id as event_id, splits.id as split_id 
FROM raw_times
INNER JOIN event_groups ON event_groups.id = raw_times.event_group_id
INNER JOIN events ON events.event_group_id = event_groups.id
INNER JOIN efforts ON efforts.event_id = events.id
INNER JOIN aid_stations ON aid_stations.event_id = events.id
INNER JOIN splits ON splits.id = aid_stations.split_id
WHERE efforts.bib_number::text = raw_times.bib_number
AND splits.parameterized_base_name = raw_times.parameterized_split_name

这个想法是找到匹配的号码布号码和拆分名称,并返回填充了各种关系 ID 的 raw_time 记录。

用简单的英语来说,逻辑是这样工作的:对于每个 raw_time,检查 event_group_id。一个 event_group 有很多事件,一个事件有很多努力,努力表有一个 bib_number 列。号码在一个 event_group 中是唯一的,但在整个 efforts 表中不是唯一的。

因此对于每个 raw_time,因为我们知道 event_group_id 和 bib_number,所以我们可以确定它与哪个工作相关。了解工作可以让我们也了解事件(因为工作有一个 event_id)。

一个事件通过 aid_stations 连接表有很多 split 。拆分名称在一个事件中是唯一的。因为我们知道事件(如上所述确定)并且我们知道拆分名称(它是 raw_times 表中的一列),所以我们可以确定 split_id。

对于有匹配的号码布号码和分组名称的记录,查询按预期工作。但是对于号码布或者赛段名不匹配的记录,WHERE子句不满足,所以根本不返回raw_time记录。

我尝试用 LEFT JOIN 代替每个 INNER JOIN 进行查询,但我得到了相同的结果。

我想要的是返回所有raw_time记录,但是如果没有匹配的split name,则返回split_id为NULL的记录,如果没有匹配的号码布,则返回为NULL的记录effort_id、event_id 和 split_id。

raw_times 表如下所示:

id  event_group_id  parameterized_split_name  bib_number
3 53 finish 11
4 53 finish 603
5 53 finish 9999
6 53 nonexistent 603

event_groups 表如下所示:

id
53
51

事件表如下所示:

id  event_group_id
26 53
28 53
18 51

工作表如下所示:

id      event_id  bib_number
22183 26 11
22400 28 603
5747 18 11

aid_stations 表如下所示:

id   event_id  split_id
236 26 30
237 26 31
238 26 106
239 26 111
240 26 112
241 26 109
242 26 113
254 28 119
255 28 118
138 18 1
150 18 16

拆分表如下所示:

id  parameterized_base_name
30 finish
31 start
106 aid-1
109 aid-4
111 aid-2
112 aid-3
113 aid-5
118 start
119 finish
1 start
16 finish

查询应该返回这个:

id  event_group_id parameterized_split_name bib_number effort_id event_id  split_id
3 53 finish 11 22183 26 30
4 53 finish 603 22400 28 119
6 53 nonexistent 603 22400 28 NULL
5 53 finish 9999 NULL NULL NULL

这是 ERD 的链接:https://github.com/SplitTime/OpenSplitTime/blob/master/erd.pdf

最佳答案

通过具有示例数据和想要的结果的优势,“缺失元素”似乎是通过 split_id 的相关子查询对有限结果的需要。

rextester.com 查看在 PostgreSQL 9.6 中的工作

CREATE TABLE raw_times
(id int, event_group_id int, parameterized_split_name varchar(11), bib_number int)
;

INSERT INTO raw_times
(id, event_group_id, parameterized_split_name, bib_number)
VALUES
(3, 53, 'finish', 11),
(4, 53, 'finish', 603),
(5, 53, 'finish', 9999),
(6, 53, 'nonexistent', 603)
;


CREATE TABLE event_groups
(id int)
;

INSERT INTO event_groups
(id)
VALUES
(53)
;


CREATE TABLE efforts
(id int, event_id int, bib_number int)
;

INSERT INTO efforts
(id, event_id, bib_number)
VALUES
(22183, 26, 11),
(22400, 28, 603)
;


CREATE TABLE aid_stations
(id int, event_id int, split_id int)
;

INSERT INTO aid_stations
(id, event_id, split_id)
VALUES
(236, 26, 30),
(237, 26, 31),
(238, 26, 106),
(239, 26, 111),
(240, 26, 112),
(241, 26, 109),
(242, 26, 113),
(254, 28, 119),
(255, 28, 118)
;


CREATE TABLE splits
(id int, parameterized_base_name varchar(6))
;

INSERT INTO splits
(id, parameterized_base_name)
VALUES
(30, 'finish'),
(31, 'start'),
(106, 'aid-1'),
(109, 'aid-4'),
(111, 'aid-2'),
(112, 'aid-3'),
(113, 'aid-5'),
(118, 'start'),
(119, 'finish')
;

查询 1:

select 
r.id, r.event_group_id, r.parameterized_split_name, r.bib_number
, e.id as effort_id
, e.event_id
, s.split_id
from raw_times r
left join (
select ef.id, ef.event_id, ef.bib_number, ev.event_group_id
from efforts ef
inner join events ev on ef.event_id = ev.id
) e on r.bib_number = e.bib_number
and e.event_group_id = r.event_group_id
left join lateral (
select a.split_id from aid_stations a
inner join splits s on a.split_id = s.id
where a.event_id = e.event_id
and s.parameterized_base_name = r.parameterized_split_name
limit 1) s on true
order by r.bib_number, r.id
;

结果:

| id | event_group_id | parameterized_split_name | bib_number | effort_id | event_id | split_id |
|----|----------------|--------------------------|------------|-----------|----------|----------|
| 3 | 53 | finish | 11 | 22183 | 26 | 30 |
| 4 | 53 | finish | 603 | 22400 | 28 | 119 |
| 6 | 53 | nonexistent | 603 | 22400 | 28 | (null) |
| 5 | 53 | finish | 9999 | (null) | (null) | (null) |

注意。如果使用旧版本的 Postgres,则可以在 select 子句中使用相关子查询来代替上面看到的 left join lateral

关于当 WHERE 不匹配时返回具有特定 NULL 值的记录的 SQL 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49869487/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com