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 将不符合条件。

我认为您可以在此处使用 FILTERPARTITION BY 关键字。这不是复制粘贴解决方案,但我认为这会为您指明正确的方向。我使用 10 作为行限制,因为我不想拿出假数据,但可以在那里应用 250

本例中的 table test 将是两个 table 之间初始连接的结果。 Selecting 所有数据(或所需字段)并添加 ROW_NUMBER

想法:

  1. 最内层查询:Select 所需数据并应用 ROW_NUMBER
  2. 中间查询:将行限制应用于初始结果(行号为<= x)。 Select 行限制下所有内容的最大值 x 和包括行限制在内的整个集合的最大值 x
  3. 最外层查询:确保行号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。