`
lovejuan1314
  • 浏览: 342879 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

PostgreSQL 的Distinct on

阅读更多
今天上午处理一个SQL语句的问题,情况是,有一个clicks表,以及geoip和geoip_location表。
clicks表中存取的是客户的点击数,geoip和geoip_location分别存储了各个国家的ip网段和地址信息。
通过如下SQL可以看出每一个ip符合条件的点击数
select count(click_ip) as count,click_ip from 
fb_fy_clicks 
where earn_id = 191 AND if_pay='t' AND date(crdate)='2007-12-24' 
group by click_ip;

下面通过ip找到所在的国家
select * from 
(select count(click_ip) as count,click_ip from fb_fy_clicks 
where earn_id = 191 AND if_pay='t' AND date(crdate)='2007-12-24' 
group by click_ip) as tb 
left join geoip G 
on ip4(tb.click_ip) <<= G.network 
left join geoip_location as geoip 
on G.location_id = geoip.id

这样虽然说通过ip找到国家了,但是有的ip是别人通过代理或者伪装的ip,所以有多条ip的重复记录,尽管这些只是少数,但是我们需要把这些对应多个国家的ip按照1个来算。如果仅仅使用distinct我们无法过滤掉多出来的国家。正好postgresql有distinct on

文档记载:

我们还可以用任意表达式来判断什么行可以认为是独立的:

SELECT DISTINCT ON (expression [, expression ...]) select_list ...

这里 expression 是任意值表达式, 它为所有行计算。如果一个行集合里所有行计算出的该表达式的值是一样的, 那么我们认为它们是重复的并且因此只有第一行保留在输出中。 请注意这里的一个集合的"第一行"是不可预料的, 除非你在足够多的字段上对该查询排了序,保证到达DISTINCT过滤器的行的顺序是唯一的。 (DISTINCT ON处理是发生在ORDER BY排序后面的。)

DISTINCT ON子句不是 SQL 标准的一部分, 有时候有人认为它是一个糟糕的风格,因为它的结果是不可判定的。 如果用有选择的GROUP BY和在FROM中的子查询,那么我们可以避免使用这个构造, 但是通常它是更方便的候选方法。

正好符合需求:

将SQL改为:

select distinct on (click_ip) click_ip,network,country,count from (
(select count(click_ip) as count,click_ip from fb_fy_clicks
 where earn_id = 191 AND if_pay='t' AND date_trunc('day',crdate)='2007-12-24' 
group by click_ip) as tb left join geoip G 
on ip4(tb.click_ip) <<= G.network 
left join geoip_location as geoip 
on G.location_id = geoip.id) as tmp


还有一种情况就是,有些client_ip重复的记录不需要被过滤掉,比如一些client_ip重复的记录,但是他的data_platform字段是不一样的,这样的记录是不应该被过滤掉的。这时,我们使用
 SELECT DISTINCT ON (client_ip,data_platform) client_ip,SUM(impressions) AS  impressions,crdate,data_platform from views a,ads b 
 WHERE a.ad_id = b.id  
 GROUP BY client_ip,data_platform,crdate


真实例子:

SELECT ad_id,country,SUM(impressions) AS impressions,dates,source FROM 
(SELECT  DISTINCT ON (client_ip,ad_id,source) client_ip,ad_id,COALESCE(country,'OTHER') AS country,impressions,dates,source FROM 
(((SELECT DATE_TRUNC('DAY',a.crdate) AS dates,b.ad_id,a.client_ip,COUNT(a.fb_uid) AS impressions, 0 AS source FROM views_20081020 a,ads b WHERE a.ad_id = b.id  AND a.fb_uid IS NOT NULL GROUP BY b.ad_id,a.client_ip,dates ORDER BY b.ad_id asc) 
UNION ALL 
(SELECT DATE_TRUNC('DAY',a.crdate) AS dates,b.ad_id,a.client_ip,COUNT(a.bebo_uid) AS impressions, 1 AS source FROM views_20081020 a,ads b WHERE a.ad_id = b.id  AND a.bebo_uid IS NOT NULL GROUP BY b.ad_id,a.client_ip,dates ORDER BY b.ad_id asc )UNION ALL 
(SELECT DATE_TRUNC('DAY',a.crdate) AS dates,b.ad_id,a.client_ip,COUNT(a.ms_uid) AS impressions, 2 AS source FROM views_20081020 a,ads b WHERE a.ad_id = b.id  AND a.ms_uid IS NOT NULL  GROUP BY b.ad_id,a.client_ip,dates ORDER BY b.ad_id asc ) 
UNION ALL 
(SELECT DATE_TRUNC('DAY',a.crdate) AS dates,b.ad_id,a.client_ip,COUNT(a.hi5_uid) AS impressions, 3 AS source FROM views_20081020 a,ads b WHERE a.ad_id = b.id  AND a.hi5_uid IS NOT NULL GROUP BY b.ad_id,a.client_ip,dates ORDER BY b.ad_id asc)) AS tmp_ads_imprs_country_stats 
LEFT JOIN geoip G ON ip4(tmp_ads_imprs_country_stats.client_ip) <<= G.network  LEFT JOIN geoip_location AS geoip_loc ON G.location_id = geoip_loc.id ) AS tmp_ads_imprs_country_stats_t ) AS FOO GROUP BY ad_id,country,dates,source ORDER BY ad_id ASC;

分享到:
评论

相关推荐

    oracle中使用group by优化distinct

    4. **使用`DISTINCT ON`(Oracle不支持,但其他数据库如PostgreSQL支持)**:虽然Oracle不直接支持`DISTINCT ON`,但可以尝试通过子查询或窗口函数模拟此功能。例如,你可以先用`ROW_NUMBER()`分配唯一的行号,然后...

    postgresql中的ltree类型使用方法

    select distinct s.name from tmp.ltree_table s where subltree(s.path,1,2) = '南城'; ``` 此外,可以计算路径的层级,即标签的数量: ```sql select s.name, nlevel(s.path) from tmp.ltree_table s; ``` 通过...

    PostGresql工作中一条复杂SQL解析

    ) t2 ON t2.dateOfDay = t1.dateOfDay ORDER BY t1.dateOfDay; ``` 这里,我们使用`COALESCE`函数将空值转换为0,以确保每个日期都有对应的付费用户数。 4. **格式化输出**:最后,我们可能希望日期字段显示为"MM/...

    talk-bashtanov-160706213218.pdf

    这些示例不仅包括了基础的GROUP BY聚合查询,还涉及到了DISTINCT ON语句以及聚合操作与其他SQL功能(如ORDER BY、LIMIT等)的结合使用,从而使读者能够更直观地理解聚合操作在实际应用中的灵活性与强大功能。...

    数据库认证考试题.pdf

    SELECT * FROM exam.orders JOIN exam.city ON exam.orders.CityCode = exam.city.CityCode WHERE exam.city.CityName = '北京'; ``` **知识点11:字符串操作** - **提取子字符串**: 使用SQL函数如`SUBSTRING`...

    实验报告sql1

    这条语句非常简单明了,适用于大多数关系型数据库管理系统(RDBMS),如MySQL、PostgreSQL等。 ### 二、找出所有零件的名称、颜色、重量 此部分的目标是获取零件表(`P`)中的零件名称(`Pname`)、颜色(`color`)以及...

    jet:具有代码生成和自动查询结果数据映射的类型安全SQL Builder

    动机内容产品特点自动生成的类型安全SQL Builder PostgreSQL: (DISTINCT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT, OFFSET, FOR, UNION, INTERSECT, EXCEPT, WINDOW, sub-queries) (VALUES, MODEL, MODELS...

    一条sql语句关联八个表

    在实际应用中,使用数据库管理工具如MySQL、Oracle、SQL Server或PostgreSQL等时,可以通过它们提供的图形化界面来构建和理解这些复杂的联接查询,这对初学者来说更加直观。 总之,关联八个表的SQL语句虽然复杂,但...

    两个表中查询出不同的数据

    例如,对于关系型数据库,MySQL、PostgreSQL、Oracle等都支持上述查询语法;而对于非关系型数据库,如MongoDB,可能需要使用不同的查询语言和方法。此外,数据处理工具如SQLAlchemy(Python)、JDBC(Java)或Entity...

    leecode-数据库题(全).pdf

    具体是在查询中使用了关键字LEFT JOIN来联接Person表和Address表,并通过ON语句指定了联接的条件,即Person表的PersonId和Address表的PersonId相匹配。 ### 2. SQL右联接(RIGHT JOIN)与内联接(INNER JOIN) 在...

    智能SQL优化与改写.pptx

    例如,对一个未经优化的查询如`SELECT COUNT(DISTINCT user_id) AS TOTAL FROM tbl WHERE d = 3 AND q = 4;`进行优化,可能需要添加合适的索引来提升性能。 查询优化的难点包括语法检查和逻辑判断,如在更新语句中...

    oracle考试题目.docx

    - SQL语句:`SELECT DISTINCT d.dept_name FROM dept d JOIN emp e ON d.deptno = e.deptno;` 16. **列出各个部门的MANAGER(经理)的最低薪金。** - 先找出各部门的经理,然后计算最低薪金。 - SQL语句:`...

    sql入门教程

    SQL(Structured Query Language)是用于存储、检索和操作关系型数据库的标准...在实际应用中,根据数据库的具体类型(如MySQL、PostgreSQL、SQL Server等),具体的SQL语法可能会略有差异,但基础概念和结构是通用的。

    SQL结构化查询语言简介_sql_

    它被广泛应用于各种数据库管理系统,如MySQL、Oracle、SQL Server、PostgreSQL等。SQL的主要功能包括数据查询、数据更新、数据插入和数据删除。下面将详细介绍SQL的一些核心知识点。 1. 数据查询:SQL中最基础的...

    SQL入门教程大全2024

    - **特定数据库系统**: 关注MySQL、SQL Server、Oracle、PostgreSQL等相关教程和文档。 通过以上详细的内容,初学者可以从SQL的基础概念入手,逐步掌握数据库操作的核心技能,从而有效地管理和操作关系型数据库。

    常用SQL_sql_

    9. **聚合函数**:除了`COUNT`、`SUM`、`AVG`、`MIN`、`MAX`之外,还有`GROUP_CONCAT`(组合多个值为一个字符串)和`DISTINCT`(去除重复值)等。 10. **集合操作**:`UNION`、`UNION ALL`、`INTERSECT`和`EXCEPT`...

    数据库教程

    常见的DBMS包括Oracle、Microsoft SQL Server、MySQL、PostgreSQL等。 - **关系型数据库**:基于关系模型构建的数据库,数据被组织成表格形式,通过行和列来表示数据和它们之间的联系。 - **非关系型数据库(NoSQL)**...

    sql21自学通

    - SELECT [DISTINCT] * | column_name [, column_name ...] - FROM table_name - [WHERE condition] - [GROUP BY column_name [, column_name ...]] - [HAVING condition] - [ORDER BY column_name [, column_...

    sql-101

    例如,`SELECT Customers.CustomerName, Orders.OrderID FROM Customers JOIN Orders ON Customers.CustomerID=Orders.CustomerID`将显示每个客户的订单ID。 - **WHERE**:用于过滤结果集,只返回满足特定条件的...

Global site tag (gtag.js) - Google Analytics