来自某个SELECT语句的重复数据
我正在用PostgreSQL创建一个根据用户姓名来查询数据的函数,但当参数中没有传入姓名时,它应该返回所有预约,且不受姓名影响;然而我却得到了重复的数据。因为只有John Doe与之相关的预约存在,这个Ian F不应该出现在结果中。
| 姓名 | 时长 | 预约时间 |
|---|---|---|
| John Doe | 50 | 2026-03-24 10:00:00 |
| Ian F | 50 | 2026-03-24 10:00:00 |
正如你所见,数据被重复了,因为Ian F没有任何预约,他只是复制了John Doe的数据。由于我不知道在PostgreSQL中如何调试,我也不太清楚这是为什么。
该函数。
CREATE or replace FUNCTION get_appointment(customerName varchar, companyNickname varchar) RETURNS TABLE (name varchar, duration int, scheduled timestamp)
as $$
BEGIN
IF customerName is null OR TRIM(customerName) = '' THEN
return query
SELECT c.user_name, d.service_duration, b.scheduled_time from company_tb a
join schedules_tb b on a.id = b.company_id
join users_tb c on a.id = c.company_id
join services_tb d on a.id = d.company_id
where b.service_id = d.id
and a.company_nickname = companyNickname
and b.scheduled_time > CURRENT_TIMESTAMP;
ELSE
return query
SELECT c.user_name, d.service_duration, b.scheduled_time from company_tb a
join schedules_tb b on a.id = b.company_id
join users_tb c on a.id = c.company_id
join services_tb d on a.id = d.company_id
where b.service_id = d.id
and c.user_name = customerName
and a.company_nickname = companyNickname
and b.scheduled_time > CURRENT_TIMESTAMP;
END IF;
END
$$LANGUAGE plpgsql;
SELECT * from get_appointment('', 'agendaai-barber');
表的定义和数据。
company_tb
| 创建时间 | ID | 名称 | 昵称 | 方案 |
|---|---|---|---|---|
| 2026-03-23 16:11:08 | 1 | AgendaAI Barber Shop | agendaai | 免费 |
schedules_tb b
| 公司ID | 客户ID | ID | 日程 | 服务ID | 用户ID |
|---|---|---|---|---|---|
| 1 | 1 | 1 | 2026-03-24 10:00:00 | 1 | 1 |
| 1 | 2 | 2 | 2026-03-24 11:00:00 | 3 | 1 |
| 1 | 3 | 3 | 2026-03-24 12:00:00 | 1 | 1 |
| 1 | 4 | 4 | 2026-03-24 15:00:00 | 1 | 1 |
| 1 | 5 | 5 | 2026-03-25 08:00:00 | 2 | 1 |
| 1 | 6 | 6 | 2026-03-25 10:00:00 | 1 | 1 |
| 1 | 7 | 7 | 2026-03-26 10:00:00 | 1 | 1 |
users_tb
| 公司ID | ID | 创建时间 | 邮箱 | 姓名 | 角色 |
|---|---|---|---|---|---|
| 1 | 1 | 2026-03-24 10:00:00 | email@mail | John Doe | ADM |
| 1 | 2 | 2026-03-24 11:00:00 | email@mail | Ian F | USER |
services_tb
| 时长 | 价格 | ID | 公司ID | 描述 | 名称 |
|---|---|---|---|---|---|
| 60 | 40 | 1 | 1 | 经典男士理发 | 理发 |
| 20 | 20 | 2 | 1 | 胡须修剪 | 胡须修剪 |
解决方案
你在 schedules_tb.user_id 与 users_tb.id 之间缺少一个连接条件。
此外,这个函数也可能更适合作为一个普通的 sql 函数,而不是 pgpsql,这将便于内联。你还应该使用比a、b、c更易理解的别名,并给表命名为 _tb,这确实有点麻烦。
CREATE or replace FUNCTION get_appointment
(customerName varchar, companyNickname varchar)
RETURNS TABLE (name varchar, duration int, scheduled timestamp)
as $$
SELECT
u.name,
sv.duration,
sc.schedule
from company_tb c
join schedules_tb sc on c.id = sc.company_id
join users_tb u on c.id = u.company_id and sc.user_id = u.id
join services_tb sv on c.id = sv.company_id and sc.service_id = sv.id
where customerName <> ''
and u.name = customerName
and c.nickname = companyNickname
and sc.schedule > CURRENT_TIMESTAMP
UNION ALL
SELECT
u.name,
sv.duration,
sc.schedule
from company_tb c
join schedules_tb sc on c.id = sc.company_id
join users_tb u on c.id = u.company_id and sc.user_id = u.id
join services_tb sv on c.id = sv.company_id and sc.service_id = sv.id
where (customerName is null or customerName = '')
and c.nickname = companyNickname
and sc.schedule > CURRENT_TIMESTAMP;
$$LANGUAGE sql;
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。