简体   繁体   English

如何使我的 PostgreSQL select 查询更短?

[英]How can I make my PostgreSQL select query shorter?

I am working on the website and I need to execute a pretty complex select query.我正在网站上工作,我需要执行一个非常复杂的 select 查询。 I managed to write it, but It looks too long for me and I want to make it shorter.我设法写了它,但它看起来对我来说太长了,我想让它更短。 Here is my query:这是我的查询:

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;

Does anyone have idea how to make it shorter?有谁知道如何使它更短?

How about just doing this?只做这个怎么样?

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;

See the addition of having clause.请参阅添加having子句。

Shorter?更短? (And correct?!) (对吗?!)

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;  -- ④

① Changed all three instances of LEFT JOIN to [INNER] JOIN , since the condition on the last table in the food chain ( meeting ) forces all joins to behave like plain joins anyway. ① 将LEFT JOIN的所有三个实例更改为[INNER] JOIN ,因为食物链( meeting )中最后一张表上的条件强制所有连接的行为无论如何都像普通连接。 (As @wildplasser pointed out.) See: (正如@wildplasser 指出的那样。)请参阅:

Also, if column names are identical and distinct among all tables left of the join, USING is convenient short syntax.此外,如果连接左侧的所有表中的列名相同且不同,则USING是一种方便的短语法。 (Returning only one of each pair of joined columns, which has no bearing on the query at hand.) (仅返回对连接列中的一个,这与手头的查询无关。)

Not knowing exact table definitions, I only applied it in the first join, where ambiguities are impossible as there is only a single table left of the join.不知道确切的表定义,我只在第一个连接中应用了它,因为连接只剩下一个表,所以不可能有歧义。 For persisted queries, generally only advisable if involved column names are stable and distinct over all joined tables.对于持久化查询,通常仅在所涉及的列名在所有连接表中稳定且不同的情况下才可取。

② Typically, you'd want to exclude the upper bound and BETWEEN is the wrong tool . ② 通常,您希望排除上限,而BETWEEN是错误的工具 Related:有关的:

③ About this short syntax: ③ 关于这个简短的语法:

Possibly shorter if there are functional dependencies with PK columns.如果 PK 列存在功能依赖关系,可能会更短。 See:看:

count(*) is shorter & faster (and equivalent in this case). count(*)更短更快(在这种情况下等效)。 Also, can be used in HAVING clause without listing in SELECT list.此外,可以在HAVING子句中使用,而不在SELECT列表中列出。 See:看:

⑤ All source column names should be table-qualified, if only for documentation. ⑤ 所有源列名都应该是表限定的,如果仅用于文档。 Also avoids breakage and confusion from later changes to underlying tables.还避免了后来对基础表的更改造成的破坏和混乱。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM