我正在网站上,我需要执行一个非常复杂的选择查询。我设法写了,但是对我来说似乎太长了,我想把它缩短些。这是我的查询:
select friend_id, name, surname, mail, birth_date, address
from (select friend_id, name, surname, mail, birth_date, address, count(friend_id) as rents
from (select friend.friend_id, name, surname, mail, birth_date, address
from friend
left join profile p on friend.profile_id = p.profile_id
left join friend_group_record fgr on friend.friend_id = fgr.friend_id
left join meeting m on fgr.friend_group_id = m.friend_group_id
where m.date between '2019-09-01' and '2020-01-01') as filtered_friend_profiles
group by friend_id, name, surname, mail, birth_date, address) as counted_friend_profiles
where counted_friend_profiles.rents >= 25;
有人知道如何使其更短吗?
答案 0 :(得分:1)
怎么做?
select friend.friend_id, name, surname, mail, birth_date, address
from friend
left join profile p on friend.profile_id = p.profile_id
left join friend_group_record fgr on friend.friend_id = fgr.friend_id
left join meeting m on fgr.friend_group_id = m.friend_group_id
where m.date between '2019-09-01' and '2020-01-01'
group by friend.friend_id, name, surname, mail, birth_date, address
having count(friend.friend_id) >= 25;
请参见having
子句的添加。
答案 1 :(得分:1)
更短? (对吗?!)
SELECT f.friend_id, name, surname, mail, birth_date, address -- ⑤
FROM friend f
JOIN profile p USING (profile_id) -- ①
JOIN friend_group_record fgr ON f.friend_id = fgr.friend_id -- also USING?
JOIN meeting m ON fgr.friend_group_id = m.friend_group_id -- also USING?
WHERE m.date >= '2019-09-01' -- ②
AND m.date < '2020-01-01'
GROUP BY 1, 2, 3, 4, 5, 6 -- ③
HAVING count(*) >= 25; -- ④
①将LEFT JOIN
的所有三个实例更改为[INNER] JOIN
,因为食物链中最后一个表(meeting
)上的条件始终迫使所有联接的行为类似于普通联接。 (如@wildplasser指出的。)请参阅:
此外,如果列名称在联接的所有剩余表中相同且不同,则USING
是方便的简短语法。 (每对联接列中仅返回一个,这与当前查询无关。)
不知道确切的表定义,我只在第一个连接中应用了它,因为连接中只剩下一个表,所以在这里不会出现歧义。对于持久化查询,通常仅在所涉及的列名稳定且在所有联接表中都不同的情况下才建议使用
。②通常,您要排除上限和BETWEEN
is the wrong tool。相关:
③关于此简短语法:
如果PK列具有功能依赖性,则可能更短。参见:
④count(*)
短且快(在这种情况下等效)。另外,可以在HAVING
子句中使用,而无需在SELECT
列表中列出。参见:
⑤如果仅出于说明目的,所有源列名称都应为表限定的。还避免了以后对基础表的更改造成的破坏和混乱。