编写SQL查询,选择列值从上一行更改的行

时间:2017-09-12 06:42:11

标签: postgresql

CREATE TABLE status( id serial NOT NULL,
id integer,
plan smallint,
ime timestamp without time zone
CONSTRAINT data_pkey PRIMARY KEY (id))
WITH (OIDS=FALSE);
ALTER TABLE data
OWNER TO postgres;

索引:data_idx

CREATE INDEX data_idx
ON data
USING btree
(time, id);

我有一张这样的表

id    val         plan     time
 1    8300        1      2011-01-01        
 2    8300        1      2011-01-02         
 3    8300        2      2011-01-03         
 4    9600        1      2011-01-04         
 5    9600        2      2011-01-05      

如何选择sigplan从该siteId的上一行更改的行?

在上面的示例中,查询应返回行

2011-01-03 (sigplan changed from 1 to 2 between 2011-01-01 and 2011-01-03 for 8300), 
2011-01-05(sigplan changed from 1 to 2 between 2011-01-04 and 2011-01-05 for 9600).
  • 该表包含大量数据,因此应优化查询。

3 个答案:

答案 0 :(得分:0)

烦人的部分是弄清楚哪个是具有相同siteId的前一行id。之后,通过自己加入表格非常容易。

SELECT t1.* FROM table t1, table t2 
WHERE t1.sigplan != t2.sigplan 
AND t2.id = (SELECT MAX(t3.id) FROM table t3 WHERE t3.id < t1.id)

如果表格适度(非常大),我会考虑在应用程序代码中执行此操作,或者在编写新行时将更改标志存储在其自己的列中。表中每行的子查询性能非常差。

答案 1 :(得分:0)

SELECT siteId, sigplan, MAX(server_time) FROM traffview.status_data 
GROUP BY siteId, sigplan   
HAVING COUNT(1) > 1 AND MAX(server_time) > 'XXXXX' AND MAX(server_time) < 'XXXXX'

答案 2 :(得分:0)

此版本没有子查询,但假设您有连续的ID。

SELECT t1.* 
FROM traffview AS t1, traffview AS t2 
WHERE 
    t1.siteId = t2.siteId 
    AND t1.sigplan <> t2.sigplan
    AND t1.id - t2.id = 1
ORDER BY 
    t1.server_time