首页 > 解决方案 > 如何仅对一列使用“不同”?

问题描述

我有一个查询来检查我拥有的一些“位置”表的访问。如果用户使用“emp”或“oth”的推荐进行注册,则他们的第一次访问不应计入,但第二次访问和转发应计入。

我正在尝试计算每个位置的“首次访问”。每当他们访问时,我都会记录它在哪个位置。

问题是我的查询计数正确,但有些用户访问了不同的位置。因此,不是只计算该位置的一次访问(第一次),而是在用户访问过的每个位置添加一个。

这是我的查询

SELECT COUNT(DISTINCT CASE WHEN customer.ref IN ('emp', 'oth') THEN customer.id END) as visit_count, locations.name as location FROM locations
LEFT JOIN visits ON locations.location_name = visits.location_visit_name
LEFT JOIN customer ON customer.id = visits.customer_id
WHERE locations.active = true
GROUP BY locations.location_name, locations.id;

我得到的结果是

visit_count |  locations
-------------------------
    7       |      Loc 1
    3       |      Loc 2
    1       |      Loc 3

应该如何:

visit_count |  locations
-------------------------
    6       |      Loc 1
    2       |      Loc 2
    1       |      Loc 3

因为这些人中有 2 人在这两个位置都访问过,所以每个位置都计算一个。我认为这DISTINCT也是为地点做的,而它应该只在计数时customer.id

有没有办法可以在我的查询中添加一些东西来获取第一次访问的位置,而不关心他们是否在其他位置进行了其他访问?

标签: postgresql

解决方案


如果我正确地跟踪了您,您只想计算每个客户的第一次访问,按位置分布。

一种解决方案是在相关on子句中使用相关子查询join来过滤首次客户访问。假设该列visit(visit_date)存储每次访问的日期,您可以执行以下操作:

select 
    count(c.customer_id) visit_count,
    l.name as location
from locations l
left join visits v 
    on  l.location_name = v.location_visit_name
    and v.visit_date = (
        select min(v1.visit_date)
        from visit v1
        where v1.customer_id = v.customer_id
    )
left join customer c 
    on  c.id = v.customer_id 
    and c.ref in ('emp', 'oth')
where l.active = true
group by l.location_name, l.id;

旁注:

  • 在每个客户的第一次访问时适当地拟合避免了distinctcount()聚合函数的需要

  • 表别名使查询更简洁,更容易理解;我建议在所有查询中使用它们

  • 过滤器customer(ref)放在where子句中比作为条件计数条件更好


推荐阅读