[英]ROW_NUMBER() shows unexpected values
我的表具有類似的值( 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中嘗試了相同的查詢,並找到了相同的結果。
我在這里上傳了一個csv數據示例 。
我被分區的這種意外結果所困擾。 有誰能夠幫助我?
ROW_NUMBER()
函數的PARTITION BY
子句指示它對由Price
值設置的整個行進行分區,並以ID
的升序分配行號。
似乎您想區分具有相同Price
值的任何兩組行,這些行之間至少由具有不同Price
一行分隔開 。
可能有多種方法可以實現這一目標。 在SQL Server中(我認為同樣適用於PostgreSQL),我將首先使用兩個ROW_NUMBER()
調用來獲取附加的分區條件,然后使用該條件再次對行進行排名,如下所示:
WITH partitioned AS (
SELECT
ID,
Date_trans,
Time_trans,
Price,
ROW_NUMBER() OVER ( ORDER BY ID) -
ROW_NUMBER() OVER (PARTITION BY Price ORDER BY ID) AS PriceGroup
FROM MyTable
)
SELECT
ID,
Date_trans,
Time_trans,
Price,
ROW_NUMBER() OVER (PARTITION BY Price, PriceGroup ORDER BY ID) AS RowCount
FROM partitioned
ORDER BY ID
;
這是一個SQL Fiddle演示 。
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的解決方案稍微優雅一點。 它也需要三個窗口函數,但是只能在兩個查詢步驟中完成。 在對小樣品的快速測試中,它的速度也稍快一些。 因此,我+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
:您可以通過將date_trans date
和time_trans time
合並到ts_trans timestamp
來簡化表(和查詢)並節省一些存儲字節。
使用timestamp
從timestamp
提取date
或time
非常簡單且非常快速:
ts_trans::date
ts_trans::time
1699100價格58.0-顯示3因為1699097,8是1,2
1699104價格57.96 –顯示2,因為1669101為1。
1699105,1699106價格57.93 –顯示2、3,因為1699103是1
如果要在序列中查找具有相同值的項目,一種選擇是將數據連接到先前的ID,並查看值是否相同
根據您對結果的期望,我可以收集到的信息,您也需要對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
我認為是這種情況,因為您希望當時間轉換值隨着數據的處理而變化時,ROW_NUMBER重新開始。
另外,如果表中可能有多個日期,您可能也想在其中添加Date_trans,這是我期望的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.