ROW_NUMBER(), PARTITION_BY, TOP 2 MAX If MAX 第一个和最后一个位置
ROW_NUMBER(), PARTITION_BY, TOP 2 MAX If MAX 1st and Last Position
我有一个查询使用 ROW_NUMBER() 和 PARTITION BY 以及基于日期列的订单。我想知道的是,如果第二个最大值在位置 1 而当前最大值在位置 250,是否可以限制这个和 return 只有 col1 匹配。
SELECT t1.col1, t1.col_date, t1.col_val, t1.rno FROM (
SELECT col1, col_date, col_val, count(*), ROW_NUMBER() OVER (PARTITION BY col1 order by col_date ASC) as rno
FROM table_one
INNER JOIN
table_two
ON
table_one.id = table_one_id
WHERE col1 in (
SELECT
col1
FROM
table_one
INNER JOIN table_two on table_one.id = table_one_id
GROUP
by table_one.id
HAVING
COUNT(*) >= 250
)
GROUP BY col1, col_date, col_val
) t1
WHERE t1.rno < 250
GROUP BY t1.col1, t1.col_date, t1.col_val, t1.rno
ORDER BY t1.col1, t1.col_date;
IE-
col1 | col_date | col_val | rno
--------+----------------------------+--------+-----
ABC | 2018-07-18 15:27:35.394051 | 999 | 1
...
ABC | 2019-03-24 15:27:34.78493 | 1000 | 250
XYZ | 2018-07-18 15:27:35.394051 | 900 | 1
...
XYZ | 2019-03-24 15:27:34.78493 | 1001 | 250
如果 col_val 是 rno 1 的第二个最大值并且 col_val 是 rno 250 的最大值,那么两者都会被 returned。
[更新]
为清楚起见:两个表。 table_one 是股票代码列表。 table_two 是历史价格列表。当前查询从 table_one 中选择交易品种,并从 table_two 中加入每个交易品种有 250 多条记录的历史价格,并且 rno 的截止值为 250,因此输出将如下所示。
symbol | market_close_date | close | rno
--------+----------------------------+--------+-----
FAKE | 2018-07-18 15:27:35.394051 | 250.0 | 1
FAKE | 2018-07-19 15:27:35.391866 | 249.0 | 2
FAKE | 2018-07-20 15:27:35.389615 | 248.0 | 3
FAKE | 2018-07-21 15:27:35.38741 | 247.0 | 4
FAKE | 2018-07-22 15:27:35.3852 | 246.0 | 5
FAKE | 2018-07-23 15:27:35.383099 | 245.0 | 6
FAKE | 2018-07-24 15:27:35.380934 | 244.0 | 7
FAKE | 2018-07-25 15:27:35.378828 | 243.0 | 8
FAKE | 2018-07-26 15:27:35.376769 | 242.0 | 9
...
FAKE | 2019-03-24 15:27:34.78493 | 1000.0 | 250
TEST | 2018-07-18 15:27:35.396232 | 250.0 | 1
...
TEST | 2018-07-18 15:27:35.64352 | 50.0 | 250
如果 rno 1 > 2...249 且 rno 1...249 < rno 250,这对 FAKE 有效,因为 rno 1 是 249 的最大收盘价,250 是最大的收盘价,TEST 将不符合条件。
我认为您可以在此处使用 FILTER
和 PARTITION BY
关键字。这不是复制粘贴解决方案,但我认为这会为您指明正确的方向。我使用 10
作为行限制,因为我不想拿出假数据,但可以在那里应用 250
。
本例中的 table test
将是两个 table 之间初始连接的结果。 Selecting 所有数据(或所需字段)并添加 ROW_NUMBER
想法:
- 最内层查询:Select 所需数据并应用
ROW_NUMBER
- 中间查询:将行限制应用于初始结果(行号为
<= x
)。 Select 行限制下所有内容的最大值 x
和包括行限制在内的整个集合的最大值 x
- 最外层查询:确保行号
1
等于max(highest close
where rno < x
)并确保行号x
等于max在集合中(最高 close
其中 rno = x
)
SELECT *
FROM
(
SELECT *
, MAX(close) FILTER(WHERE rno < 10) OVER(PARTITION BY symbol) as "max"
, MAX(close) OVER(PARTITION BY symbol) AS second_max
FROM
(
SELECT *, ROW_NUMBER() OVER(PARTITION BY symbol ORDER BY close_date) AS rno
FROM test
) t
WHERE t.rno <= 10
) t2
WHERE (t2.rno = 1 AND t2.close = t2.max)
OR (t2.rno = 10 AND t2.close = t2.second_max)
;
Here 是一个展示这个想法的 SQLFiddle。
我有一个查询使用 ROW_NUMBER() 和 PARTITION BY 以及基于日期列的订单。我想知道的是,如果第二个最大值在位置 1 而当前最大值在位置 250,是否可以限制这个和 return 只有 col1 匹配。
SELECT t1.col1, t1.col_date, t1.col_val, t1.rno FROM (
SELECT col1, col_date, col_val, count(*), ROW_NUMBER() OVER (PARTITION BY col1 order by col_date ASC) as rno
FROM table_one
INNER JOIN
table_two
ON
table_one.id = table_one_id
WHERE col1 in (
SELECT
col1
FROM
table_one
INNER JOIN table_two on table_one.id = table_one_id
GROUP
by table_one.id
HAVING
COUNT(*) >= 250
)
GROUP BY col1, col_date, col_val
) t1
WHERE t1.rno < 250
GROUP BY t1.col1, t1.col_date, t1.col_val, t1.rno
ORDER BY t1.col1, t1.col_date;
IE-
col1 | col_date | col_val | rno
--------+----------------------------+--------+-----
ABC | 2018-07-18 15:27:35.394051 | 999 | 1
...
ABC | 2019-03-24 15:27:34.78493 | 1000 | 250
XYZ | 2018-07-18 15:27:35.394051 | 900 | 1
...
XYZ | 2019-03-24 15:27:34.78493 | 1001 | 250
如果 col_val 是 rno 1 的第二个最大值并且 col_val 是 rno 250 的最大值,那么两者都会被 returned。
[更新]
为清楚起见:两个表。 table_one 是股票代码列表。 table_two 是历史价格列表。当前查询从 table_one 中选择交易品种,并从 table_two 中加入每个交易品种有 250 多条记录的历史价格,并且 rno 的截止值为 250,因此输出将如下所示。
symbol | market_close_date | close | rno
--------+----------------------------+--------+-----
FAKE | 2018-07-18 15:27:35.394051 | 250.0 | 1
FAKE | 2018-07-19 15:27:35.391866 | 249.0 | 2
FAKE | 2018-07-20 15:27:35.389615 | 248.0 | 3
FAKE | 2018-07-21 15:27:35.38741 | 247.0 | 4
FAKE | 2018-07-22 15:27:35.3852 | 246.0 | 5
FAKE | 2018-07-23 15:27:35.383099 | 245.0 | 6
FAKE | 2018-07-24 15:27:35.380934 | 244.0 | 7
FAKE | 2018-07-25 15:27:35.378828 | 243.0 | 8
FAKE | 2018-07-26 15:27:35.376769 | 242.0 | 9
...
FAKE | 2019-03-24 15:27:34.78493 | 1000.0 | 250
TEST | 2018-07-18 15:27:35.396232 | 250.0 | 1
...
TEST | 2018-07-18 15:27:35.64352 | 50.0 | 250
如果 rno 1 > 2...249 且 rno 1...249 < rno 250,这对 FAKE 有效,因为 rno 1 是 249 的最大收盘价,250 是最大的收盘价,TEST 将不符合条件。
我认为您可以在此处使用 FILTER
和 PARTITION BY
关键字。这不是复制粘贴解决方案,但我认为这会为您指明正确的方向。我使用 10
作为行限制,因为我不想拿出假数据,但可以在那里应用 250
。
本例中的 table test
将是两个 table 之间初始连接的结果。 Selecting 所有数据(或所需字段)并添加 ROW_NUMBER
想法:
- 最内层查询:Select 所需数据并应用
ROW_NUMBER
- 中间查询:将行限制应用于初始结果(行号为
<= x
)。 Select 行限制下所有内容的最大值x
和包括行限制在内的整个集合的最大值x
- 最外层查询:确保行号
1
等于max(highestclose
whererno < x
)并确保行号x
等于max在集合中(最高close
其中rno = x
)
SELECT *
FROM
(
SELECT *
, MAX(close) FILTER(WHERE rno < 10) OVER(PARTITION BY symbol) as "max"
, MAX(close) OVER(PARTITION BY symbol) AS second_max
FROM
(
SELECT *, ROW_NUMBER() OVER(PARTITION BY symbol ORDER BY close_date) AS rno
FROM test
) t
WHERE t.rno <= 10
) t2
WHERE (t2.rno = 1 AND t2.close = t2.max)
OR (t2.rno = 10 AND t2.close = t2.second_max)
;
Here 是一个展示这个想法的 SQLFiddle。