子计数值的WHERE条件

时间:2016-02-02 11:01:00

标签: sql postgresql

我有3张桌子。

table deals
+----+------+-------------+
| id | name | location_id |
+----+------+-------------+

table deals_user_actions
+---------+---------+
| deal_id | user_id |
+---------+---------+

table locations
+----+-----------+----------+
| id | longitude | latitude |
+----+-----------+----------+

我原来的工作查询是:

SELECT d.id, d.title
FROM deals d
JOIN locations l ON l.id = d.location_id
WHERE ST_Distance_Spheroid(ST_MAKEPOINT(l.longitude, l.latitude), ST_MAKEPOINT(18, 59), 'SPHEROID[\"WGS 84\",6378137,298.257223563]') < 50

但我需要选择只有一定数量用户操作的交易,例如:

SELECT 
    d.id, 
    d.title,
    COUNT(dua.deal_id) AS numUserActions
FROM deals d
JOIN locations l ON l.id = d.location_id
JOIN deals_user_actions dua ON dua.deal_id = d.id
WHERE 
    ST_Distance_Spheroid(ST_MAKEPOINT(l.longitude, l.latitude), ST_MAKEPOINT(18, 59), 'SPHEROID[\"WGS 84\",6378137,298.257223563]') < 50
    AND numUserActions == 10

但是在这里它抱怨在GROUP BY子句中没有d.id,l.longitude和l.latitude列。但是当我添加它们时,查询中只返回一个结果。

那么您如何建议更改查询以使结果以COUNTed JOINed表为条件?

1 个答案:

答案 0 :(得分:2)

没有理由加入deals_user_actions。只需在WHERE子句中使用子选择来计算:

SELECT d.id, d.title
FROM deals d
JOIN locations l ON l.id = d.location_id
WHERE ST_Distance_Spheroid(ST_MAKEPOINT(l.longitude, l.latitude),
                           ST_MAKEPOINT(18, 59), 
                           'SPHEROID[\"WGS 84\",6378137,298.257223563]') < 50
AND (select count(*) from deals_user_actions dua where dua.deal_id = d.id) = 10

更新1:如果您想显示操作数,请改为加入汇总数据:

SELECT d.id, d.title, dua.actions
FROM deals d
JOIN locations l ON l.id = d.location_id
JOIN
(
  select deal_id, count(*) as actions
  from deals_user_actions
  group by deal_id
  having actions = 10
) dua ON dua.deal_id = d.id
WHERE ST_Distance_Spheroid(ST_MAKEPOINT(l.longitude, l.latitude),
                           ST_MAKEPOINT(18, 59), 
                           'SPHEROID[\"WGS 84\",6378137,298.257223563]') < 50

更新2 :为了完整起见,我向您展示您的原始查询仅使用GROUP BY和HAVING略微修改。你看,当要求汇总结果(这里是COUNT(*))时,你不能在WHERE中对表的记录起作用,而是在HAVING中对聚合组起作用。

但是,如上所示,加入聚合是一个好习惯,而不是先加入表格然后聚合,如下所示。 (对于后者,当您不得不使用来自多个表的聚合时,您很容易遇到问题。)

SELECT 
    d.id, 
    d.title,
    COUNT(dua.deal_id) AS numUserActions
FROM deals d
JOIN locations l ON l.id = d.location_id
JOIN deals_user_actions dua ON dua.deal_id = d.id
WHERE ST_Distance_Spheroid(ST_MAKEPOINT(l.longitude, l.latitude),
                           ST_MAKEPOINT(18, 59), 
                           'SPHEROID[\"WGS 84\",6378137,298.257223563]') < 50
GROUP BY d.id, d.title
HAVING numUserActions = 10