在此查询中计算每位客户一次

时间:2015-07-20 13:52:43

标签: mysql postgresql postgis

我有两个表:一个是商店位置列表(lat / long),另一个是客户列表(地址lat / long)。我需要的是一个查询,显示每个商店的特定范围内有多少客户。目标是让每个客户在距离商店最近的距离范围内计算一次。也就是说,每个客户只应计算一次。例如,如果他们距离一家商店2英里,距离另一家商店5英里,那么只计算它们与第一家商店相关联。

下面的查询应该完成所有这些,所以基本上我可以看到所有客户来自任何商店的最大距离。

这就是我的查询:

SELECT CASE 
WHEN dist <  8046. THEN 1 
WHEN dist <  16093. THEN 2 
WHEN dist < 40233. THEN 3 
WHEN dist < 80467. THEN 4 
WHEN dist < 160934. THEN 5 
END AS grp,count(*) 
FROM (SELECT s.id, s.identifier, ST_Distance_Sphere(s.the_geom, c.the_geom) AS dist FROM full_data_for_testing_deid_2 c, demo_locations_table s) 
AS loc_dist 
GROUP BY grp

结果如下:

| Count   | grp  |
|---------|------|
| 2860    | 1    |
| 4858    | 2    |
| 12735   | 3    |
| 11432   | 4    |
| 23950   | 5    |
| 1002970 | null |

我的数据库中只有32048个客户,所以这不是很正常。如果是的话,我希望这些数值会线性增加,但在我的结果中,第3组第4节中的客户数量更多,但情况并非如此。此外,1-5组应该加起来为32048,因为每个客户只应计算一次。

有关如何调整此项以使每位客户只计算一次的任何想法?

1 个答案:

答案 0 :(得分:1)

仅计算每位客户 一次 (在Postgres 9.3 +中):

SELECT CASE 
         WHEN s.dist < 8046.0    THEN 1 
         WHEN s.dist < 16093.0   THEN 2 
         WHEN s.dist < 40233.0   THEN 3 
         WHEN s.dist < 80467.0   THEN 4 
         WHEN s.dist < 1609340.0 THEN 5 
       END AS grp
     , count(*)
FROM full_data_for_testing_deid_2 c
   , LATERAL (
   SELECT s.id, s.identifier, ST_Distance_Sphere(s.the_geom, c.the_geom) AS dist
   FROM   demo_locations_table s
   ORDER  BY dist
   LIMIT  1
   ) s
GROUP  BY 1;

这会使每个客户完全一次并在汇总之前找到最接近它的位置。

但我不认为ST_Distance_Sphere()the_geom上使用GiST索引。 如果性能问题,请考虑ST_DWithin()