最大连胜内的行数?

发布于 2024-12-25 20:32:20 字数 356 浏览 1 评论 0原文

给定行,

symbol_id profit date
1         100    2009-08-18 01:01:00
1         100    2009-08-18 01:01:01
1         156    2009-08-18 01:01:04
1         -56    2009-08-18 01:01:06
1         18     2009-08-18 01:01:07

我如何最有效地选择涉及最大连续(利润)的行。

最大的连胜是前 3 行,我想要这些行。我想出的查询只是一堆嵌套查询和派生表。我正在寻找一种使用公用表表达式或更高级的方法来执行此操作的有效方法。

Given the Rows

symbol_id profit date
1         100    2009-08-18 01:01:00
1         100    2009-08-18 01:01:01
1         156    2009-08-18 01:01:04
1         -56    2009-08-18 01:01:06
1         18     2009-08-18 01:01:07

How would I most efficiently select the rows that are involved in the greatest streak (of profit).

The greatest streak would be the first 3 rows, and I would want those rows. The query I came up with is just a bunch of nested queries and derived tables. I am looking for an efficient way to do this using common table expressions or something more advanced.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

野心澎湃 2025-01-01 20:32:20

您尚未定义如何处理 0 利润,或者如果最长连胜平局会发生什么。但类似...

;WITH T1 AS
(
SELECT *,
       ROW_NUMBER() OVER (PARTITION BY symbol_id ORDER BY date) - 
       ROW_NUMBER() OVER (PARTITION BY symbol_id, SIGN(profit) 
                              ORDER BY date) AS Grp 
FROM  Data      
), T2 AS  
(
SELECT *,
       COUNT(*) OVER (PARTITION BY symbol_id,Grp) AS StreakLen
FROM T1       
)
SELECT TOP 1 WITH TIES *
FROM T2 
ORDER BY  StreakLen DESC

或者 - 如果您正在寻找最有利的连续走势

;WITH T1 AS
(
SELECT *,
       ROW_NUMBER() OVER (PARTITION BY symbol_id ORDER BY date) - 
       ROW_NUMBER() OVER (PARTITION BY symbol_id, CASE WHEN profit >= 0 THEN 1 END
                              ORDER BY date) AS Grp 
FROM  Data      
), T2 AS  
(
SELECT *,
       SUM(profit) OVER (PARTITION BY symbol_id,Grp) AS StreakProfit
FROM T1       
)
SELECT TOP 1 WITH TIES *
FROM T2 
ORDER BY  StreakProfit DESC

You haven't defined how 0 profit should be treated or what happens if there is a tie for longest streak. But something like...

;WITH T1 AS
(
SELECT *,
       ROW_NUMBER() OVER (PARTITION BY symbol_id ORDER BY date) - 
       ROW_NUMBER() OVER (PARTITION BY symbol_id, SIGN(profit) 
                              ORDER BY date) AS Grp 
FROM  Data      
), T2 AS  
(
SELECT *,
       COUNT(*) OVER (PARTITION BY symbol_id,Grp) AS StreakLen
FROM T1       
)
SELECT TOP 1 WITH TIES *
FROM T2 
ORDER BY  StreakLen DESC

Or - if you are looking for most profitable streak

;WITH T1 AS
(
SELECT *,
       ROW_NUMBER() OVER (PARTITION BY symbol_id ORDER BY date) - 
       ROW_NUMBER() OVER (PARTITION BY symbol_id, CASE WHEN profit >= 0 THEN 1 END
                              ORDER BY date) AS Grp 
FROM  Data      
), T2 AS  
(
SELECT *,
       SUM(profit) OVER (PARTITION BY symbol_id,Grp) AS StreakProfit
FROM T1       
)
SELECT TOP 1 WITH TIES *
FROM T2 
ORDER BY  StreakProfit DESC
哭泣的笑容 2025-01-01 20:32:20
declare @T table
(
  symbol_id int,
  profit int,
  [date] datetime
)

insert into @T values
(1,         100,    '2009-08-18 01:01:00'),
(1,         100,    '2009-08-18 01:01:01'),
(1,         156,    '2009-08-18 01:01:04'),
(1,         -56,    '2009-08-18 01:01:06'),
(1,         18 ,    '2009-08-18 01:01:07')

;with C1 as
(
  select *,
         row_number() over(order by [date]) as rn
  from @T
),
C2 as
(
  select *,
         rn - row_number() over(order by rn) as grp
  from C1
  where profit >= 0
)
select top 1 with ties *
from C2
order by sum(profit) over(partition by grp) desc

结果:

symbol_id   profit      date                    rn                   grp
----------- ----------- ----------------------- -------------------- --------------------
1           100         2009-08-18 01:01:00.000 1                    0
1           100         2009-08-18 01:01:01.000 2                    0
1           156         2009-08-18 01:01:04.000 3                    0
declare @T table
(
  symbol_id int,
  profit int,
  [date] datetime
)

insert into @T values
(1,         100,    '2009-08-18 01:01:00'),
(1,         100,    '2009-08-18 01:01:01'),
(1,         156,    '2009-08-18 01:01:04'),
(1,         -56,    '2009-08-18 01:01:06'),
(1,         18 ,    '2009-08-18 01:01:07')

;with C1 as
(
  select *,
         row_number() over(order by [date]) as rn
  from @T
),
C2 as
(
  select *,
         rn - row_number() over(order by rn) as grp
  from C1
  where profit >= 0
)
select top 1 with ties *
from C2
order by sum(profit) over(partition by grp) desc

Result:

symbol_id   profit      date                    rn                   grp
----------- ----------- ----------------------- -------------------- --------------------
1           100         2009-08-18 01:01:00.000 1                    0
1           100         2009-08-18 01:01:01.000 2                    0
1           156         2009-08-18 01:01:04.000 3                    0
电影里的梦 2025-01-01 20:32:20

如果那是 MSSQL 服务器,那么您需要考虑在 select 子句中使用 TOP 3
并按利润描述排序。
如果 mysql/postgres 您可能需要考虑在 select 子句中使用 limit
也同样的顺序。

希望这有帮助。

If that's a MSSQL server then you want to consider using TOP 3 in your select clause
and ORDER BY PROFIT DESC.
If mysql/postgres you might want to consider using limit in your select clause with
the same order by too.

hope this helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文