我的表格的值类似于(RowCount
由下面的查询生成):
ID Date_trans Time_trans Price RowCount
------- ----------- ---------- ----- --------
1699093 22-Feb-2011 09:30:00 58.07 1
1699094 22-Feb-2011 09:30:00 58.08 1
1699095 22-Feb-2011 09:30:00 58.08 2
1699096 22-Feb-2011 09:30:00 58.08 3
1699097 22-Feb-2011 09:30:00 58.13 1
1699098 22-Feb-2011 09:30:00 58.13 2
1699099 22-Feb-2011 09:30:00 58.12 1
1699100 22-Feb-2011 09:30:08 58.13 3
1699101 22-Feb-2011 09:30:09 57.96 1
1699102 22-Feb-2011 09:30:09 57.95 1
1699103 22-Feb-2011 09:30:09 57.93 1
1699104 22-Feb-2011 09:30:09 57.96 2
1699105 22-Feb-2011 09:30:09 57.93 2
1699106 22-Feb-2011 09:30:09 57.93 3
1699107 22-Feb-2011 09:30:37 58 1
1699108 22-Feb-2011 09:30:37 58.08 4
1699109 22-Feb-2011 09:30:38 58.08 5
1699110 22-Feb-2011 09:30:41 58.02 1
1699111 22-Feb-2011 09:30:41 58.02 2
1699112 22-Feb-2011 09:30:41 58.01 1
1699113 22-Feb-2011 09:30:41 58.01 2
1699114 22-Feb-2011 09:30:41 58.01 3
1699115 22-Feb-2011 09:30:42 58.02 3
1699116 22-Feb-2011 09:30:42 58.02 4
1699117 22-Feb-2011 09:30:45 58.04 1
1699118 22-Feb-2011 09:30:54 58 2
1699119 22-Feb-2011 09:30:57 58.05 1
ID
列是IDENTITY列
我正在使用此查询将连续行计数作为:
SELECT ID, Date_trans, Time_trans, Price
,ROW_NUMBER() OVER(PARTITION BY Price ORDER BY ID) RowCount
FROM MyTable
ORDER BY ID;
我得到的RowCount
对于大多数值是正确的,但对于某些值是错误的。例如:
我在PostgreSQL中尝试了相同的查询并找到了相同的结果 我上传了a csv data sample here。
我遇到了这种意想不到的分区结果。有人能帮助我吗?
答案 0 :(得分:4)
PARTITION BY
函数的ROW_NUMBER()
子句指示它按Price
值对整个行集进行分区,并按{的升序分配行号。 {1}}秒。
您似乎希望区分具有相同ID
值的任意两组行,这些值分隔至少一行具有不同的Price
。
可能有多种方法可以实现这一目标。在SQL Server中(我认为同样适用于PostgreSQL),我首先使用两个Price
调用来获得额外的分区标准,然后再使用该标准对行进行排名,如下所示:
ROW_NUMBER()
答案 1 :(得分:2)
WITH x AS (
SELECT id, date_trans, time_trans, price
,(price <> lag(price) OVER (ORDER BY id))::int AS step
FROM tbl
)
,y AS (
SELECT *, sum(step) OVER (ORDER BY id) AS grp
FROM x
)
SELECT id, date_trans, time_trans, price
,row_number() OVER (PARTITION BY grp ORDER BY id) As row_ct
FROM y
ORDER BY id;
逻辑:
step
中的最后一行相比有所变化。 (第一行的特例也适用。)grp
。老实说,我认为@Andriy's solution更优雅一点。它也需要三个窗口函数,但只能在两个查询步骤中完成。在对小样品进行快速测试时,它也略快一些。所以,+1来自我。
如果性能至关重要,那么使用
的更专业的解决方案应该快得多,因为它只需要扫描并对表进行一次排序。
CREATE OR REPLACE FUNCTION f_my_row_ct()
RETURNS TABLE (
id int
,date_trans date
,time_trans time
,price numeric
,row_ct int
) AS
$BODY$
DECLARE
_last_price numeric; -- remember price of last row
BEGIN
FOR id, date_trans, time_trans, price IN
SELECT t.id, t.date_trans, t.time_trans, t.price
FROM tbl t
ORDER BY t.id
LOOP
IF _last_price = price THEN -- works with 1st row, too
row_ct := row_ct + 1;
ELSE
row_ct := 1;
END IF;
RETURN NEXT;
_last_price = price; -- remember last price
END LOOP;
END;
$BODY$ LANGUAGE plpgsql;
呼叫:
SELECT * FROM f_my_row_ct()
在另一个小样本的快速测试中,这个速度提高了3-4倍。使用EXPLAIN ANALYZE
进行测试以查看。
顺便说一句:您可以通过将date_trans date
和time_trans time
合并到ts_trans timestamp
来简化您的表(和查询)并节省一些存储空间。
使用强制转型从date
中提取time
或timestamp
非常简单,速度非常快:
ts_trans::date
ts_trans::time
答案 2 :(得分:0)
1699100价格58.0 - 显示3,因为1699097,8是1,2
1699104价格57.96 - 显示2,因为1669101是1.
1699105,1699106价格57.93 - 显示2,3,因为1699103是1
如果要在序列中查找具有相同值的项目,一个选项是将数据连接到先前的ID并查看值是否相同
答案 3 :(得分:0)
根据你对结果的预测我可以收集的内容,你需要对Time_trans进行分区:
SELECT ID, Date_trans, Time_trans, Price
,ROW_NUMBER() OVER(PARTITION BY Time_trans, Price ORDER BY ID) RowCount
FROM MyTable
ORDER BY ID
我相信就是这种情况,因为当你在数据进展过程中Time-trans值发生变化时,你期望ROW_NUMBER重新开始。
如果表中可能有多个日期,您可能也希望在其中添加Date_trans,这是我期望的。