MySQL 每天按价值排名

发布于 2024-09-30 19:59:21 字数 902 浏览 1 评论 0原文

我正在尝试按每天 700 个交易品种的回报百分比进行排名。

例如:

date     symbol    pct_return
-----------------------------
1100101  IBM       1.2
1100101  AAPL      2.1
1100101  HPQ       -0.5

日期 1100101 大约有 700 个这样的条目

1100102  IBM       -.02
1100102  AAPL      -.6
1100102  HPQ       1.9

日期 1100102 大约有 700 个这样的

条目 我想要做的是创建一个查询或存储过程来循环每一天,然后排名并插入排名值每天每个品种的回报百分比。

我想插入百分比回报的升序和降序排名值。

排名后仅包含 3 个交易品种的示例表如下所示:

date     symbol    pct_return    rank_asc   rank_desc
------------------------------------------------------
1100101  IBM       1.2             2         2
1100101  AAPL      2.1             3         1
1100101  HPQ       -0.5            1         3
1100102  IBM       -.02            2         2
1100102  AAPL      -.6             1         3
1100102  HPQ       1.9             3         1

I am attempting to rank by % return for each day across 700 symbols.

For Example:

date     symbol    pct_return
-----------------------------
1100101  IBM       1.2
1100101  AAPL      2.1
1100101  HPQ       -0.5

approx 700 more entries like this for date 1100101

1100102  IBM       -.02
1100102  AAPL      -.6
1100102  HPQ       1.9

approx 700 more entries like this for date 1100102

What I am trying to do is create a query or stored procedure to loop through each day, and then rank and insert the rank value for the percent return for each symbol within each day.

I would like to insert the rank values for both ascending and descending ranking of percent return.

Sample table for just 3 symbols after ranking would look like:

date     symbol    pct_return    rank_asc   rank_desc
------------------------------------------------------
1100101  IBM       1.2             2         2
1100101  AAPL      2.1             3         1
1100101  HPQ       -0.5            1         3
1100102  IBM       -.02            2         2
1100102  AAPL      -.6             1         3
1100102  HPQ       1.9             3         1

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

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

发布评论

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

评论(3

浮光之海 2024-10-07 19:59:21

您可以使用此语法来选择选择中的行号:

SELECT @row := @row + 1 as row, t.*
FROM table t, (SELECT @row := 0) r;

然后您可以按每天的 ORDER BY 升序和降序选择所有值,并将它们插入到表中。

来源:http://snippets.dzone.com/posts/show/6831

示例:

INSERT INTO [your table]
SELECT date, symbol, pct_return, @row := @row + 1
FROM [your other table] t, (SELECT @row := 0) r
ORDER BY pct_return ASC;

要获取升序值,然后使用类似的查询更新同一个表以获取降序值。

You can use this syntax to select the row number in your select:

SELECT @row := @row + 1 as row, t.*
FROM table t, (SELECT @row := 0) r;

You can then select all values with ORDER BY ascending and descending for each day, and insert them into your table.

Source: http://snippets.dzone.com/posts/show/6831

Example:

INSERT INTO [your table]
SELECT date, symbol, pct_return, @row := @row + 1
FROM [your other table] t, (SELECT @row := 0) r
ORDER BY pct_return ASC;

To get the ascending values, then an update on the same table with a similar query to get the descending values.

手心的海 2024-10-07 19:59:21

这是典型的组内聚合问题,可以通过左自排除连接解决。

您不需要任何存储过程来获取所需的结果,只需一个简单的 INSERT INTO ... SELECT ... 查询即可实现。

以下是包含所提供数据的示例脚本:

CREATE TABLE shuffled_symbols ( 
   dat INT NOT NULL
  ,symbol VARCHAR(4) NOT NULL
  ,pct_return DECIMAL(4,2) NOT NULL
  ,PRIMARY KEY (dat ,symbol)
);
CREATE TABLE ranked_symbols ( 
   dat INT NOT NULL
  ,symbol VARCHAR(4) NOT NULL
  ,pct_return DECIMAL(4,2) NOT NULL
  ,rank_asc INT UNSIGNED NOT NULL
  ,rank_desc INT UNSIGNED NOT NULL
);

INSERT INTO shuffled_symbols (dat,symbol,pct_return) VALUES (1100101,'IBM',1.2);
INSERT INTO shuffled_symbols (dat,symbol,pct_return) VALUES (1100101,'AAPL',2.1);
INSERT INTO shuffled_symbols (dat,symbol,pct_return) VALUES (1100101,'HPQ',-0.5);
INSERT INTO shuffled_symbols (dat,symbol,pct_return) VALUES (1100102,'IBM',-0.02);
INSERT INTO shuffled_symbols (dat,symbol,pct_return) VALUES (1100102,'AAPL',-0.6);
INSERT INTO shuffled_symbols (dat,symbol,pct_return) VALUES (1100102,'HPQ',1.9);

这是计算排名的查询(抱歉格式错误,我无法使其在

 标签内正确显示):


插入排序符号 (
dat、符号、pct_return、rank_asc、rank_desc
) 选择 ars.dat、ars.symbol、ars.pct_return、ars.rank_asc、COUNT(ss3.dat)+1rank_desc
从 (
选择 ss1.dat、ss1.symbol、ss1.pct_return、COUNT(ss2.dat)+1rank_asc
来自 shuffled_symbols ss1
左连接 shuffled_symbols ss2
ON ss2.dat = ss1.dat
AND ss2.pct_return < ss1.pct_return
按 ss1.dat、ss1.symbol 分组
) ars
左连接 shuffled_symbols ss3
ON ss3.dat = ars.dat
和 ss3.pct_return > ars.pct_return
按 ars.dat、ars.symbol 分组
;

请注意,如果给定日期没有重复的符号,则此查询只会返回有效的排名。这就是我使用 PRIMARY KEY (dat ,symbol) 创建 shuffled_symbols 表的原因。

在ranked_symbols 表中,您将得到以下结果:

SELECT * FROM ranked_symbols;

+---------+--------+------------+----------+-----------+
| dat     | symbol | pct_return | rank_asc | rank_desc |
+---------+--------+------------+----------+-----------+
| 1100101 | AAPL   |       2.10 |        3 |         1 |
| 1100101 | HPQ    |      -0.50 |        1 |         3 |
| 1100101 | IBM    |       1.20 |        2 |         2 |
| 1100102 | AAPL   |      -0.60 |        1 |         3 |
| 1100102 | HPQ    |       1.90 |        3 |         1 |
| 1100102 | IBM    |      -0.02 |        2 |         2 |
+---------+--------+------------+----------+-----------+
6 rows in set (0.00 sec)                                

This is the typical problem of within-group aggregates that is solved with a left self exclusion join.

You don't need any stored procedure to get the results you want, just a simple INSERT INTO ... SELECT ... query will do the trick.

Here is an example script with the provided data:

CREATE TABLE shuffled_symbols ( 
   dat INT NOT NULL
  ,symbol VARCHAR(4) NOT NULL
  ,pct_return DECIMAL(4,2) NOT NULL
  ,PRIMARY KEY (dat ,symbol)
);
CREATE TABLE ranked_symbols ( 
   dat INT NOT NULL
  ,symbol VARCHAR(4) NOT NULL
  ,pct_return DECIMAL(4,2) NOT NULL
  ,rank_asc INT UNSIGNED NOT NULL
  ,rank_desc INT UNSIGNED NOT NULL
);

INSERT INTO shuffled_symbols (dat,symbol,pct_return) VALUES (1100101,'IBM',1.2);
INSERT INTO shuffled_symbols (dat,symbol,pct_return) VALUES (1100101,'AAPL',2.1);
INSERT INTO shuffled_symbols (dat,symbol,pct_return) VALUES (1100101,'HPQ',-0.5);
INSERT INTO shuffled_symbols (dat,symbol,pct_return) VALUES (1100102,'IBM',-0.02);
INSERT INTO shuffled_symbols (dat,symbol,pct_return) VALUES (1100102,'AAPL',-0.6);
INSERT INTO shuffled_symbols (dat,symbol,pct_return) VALUES (1100102,'HPQ',1.9);

Here is the query to compute ranks (sorry for the bad formatting, I couldn't make it display correctly inside <pre> tags):


INSERT INTO ranked_symbols (
dat, symbol, pct_return, rank_asc, rank_desc
) SELECT ars.dat, ars.symbol, ars.pct_return, ars.rank_asc, COUNT(ss3.dat)+1 rank_desc
FROM (
SELECT ss1.dat, ss1.symbol, ss1.pct_return, COUNT(ss2.dat)+1 rank_asc
FROM shuffled_symbols ss1
LEFT JOIN shuffled_symbols ss2
ON ss2.dat = ss1.dat
AND ss2.pct_return < ss1.pct_return
GROUP BY ss1.dat, ss1.symbol
) ars
LEFT JOIN shuffled_symbols ss3
ON ss3.dat = ars.dat
AND ss3.pct_return > ars.pct_return
GROUP BY ars.dat, ars.symbol
;

Please note that this query will only return valid ranks if you don't have duplicates of symbols for a given date. This is why I created the shuffled_symbols table with a PRIMARY KEY (dat ,symbol).

In ranked_symbols table you get the following results:

SELECT * FROM ranked_symbols;

+---------+--------+------------+----------+-----------+
| dat     | symbol | pct_return | rank_asc | rank_desc |
+---------+--------+------------+----------+-----------+
| 1100101 | AAPL   |       2.10 |        3 |         1 |
| 1100101 | HPQ    |      -0.50 |        1 |         3 |
| 1100101 | IBM    |       1.20 |        2 |         2 |
| 1100102 | AAPL   |      -0.60 |        1 |         3 |
| 1100102 | HPQ    |       1.90 |        3 |         1 |
| 1100102 | IBM    |      -0.02 |        2 |         2 |
+---------+--------+------------+----------+-----------+
6 rows in set (0.00 sec)                                
黯淡〆 2024-10-07 19:59:21

下面是我如何扩展布伦特的
以 PERL 为例。这是非常
对我有帮助,我非常感激
社区支持。

要从命令行运行代码:

rank.pl FromTableNoRank ToTableWithRank pct_return DESC

#!/usr/bin/perl -w

use strict;
use warnings;
use Carp;

// connect to database here

// Not enough command-line arguments, helpful error message.
if(@ARGV!=4) {
    die("$0 requires four arguments. 1.FromTable 2.ToTable 3.Order by value(ex.pct_return) 4.ASC (low = 1) or DESC(high = 1)\n");
}

// Use variables for insert to minimize errors
// $OrderBy is the value to rank 
// $AscDesc declares which way to rank
my $FromTable = $ARGV[0];
my $ToTable   = $ARGV[1];
my $OrderBy   = $ARGV[2];
my $AscDesc   = $ARGV[3];


// DateTable is table of dates for use within the insert query. Used to loop through and rank individual days.
my $query7 = "SELECT dat FROM DateTable ORDER BY dat ASC";
my $sth7   = $dbh->prepare($query7) || carp DBI::errstr;
$sth7->execute() || carp DBI::errstr;

// Fetchrow_hashref holds all dates from date tables and while loop walks through one at a time
// The insert sorts by a value and then a row number is added to provide a rank of values
// The nested sth exists because need to reference $dateVar from fetchrow
while(my $ref = $sth7->fetchrow_hashref()) {
    my $dateVar = $ref->{dat};
    print "$dateVar \n";
    my $query6 = "INSERT INTO $ToTable 
        SELECT t.*,". '@rownum := @rownum +1' . " 
        FROM $FromTable t, ".'(SELECT @rownum := 0) r  
        WHERE dat ='."$dateVar
        ORDER BY $OrderBy $AscDesc";
    my $sth6 = $dbh->prepare($query6) || carp DBI::errstr;
    $sth6->execute() || carp DBI::errstr;
    $sth6->finish();
}

$sth7->finish();
$dbh->disconnect();

Below is how I expanded on Brent's
example with PERL. This was very
helpful to me and I greatly appreciate
the community support.

To run the code from command line:

rank.pl FromTableNoRank ToTableWithRank pct_return DESC

#!/usr/bin/perl -w

use strict;
use warnings;
use Carp;

// connect to database here

// Not enough command-line arguments, helpful error message.
if(@ARGV!=4) {
    die("$0 requires four arguments. 1.FromTable 2.ToTable 3.Order by value(ex.pct_return) 4.ASC (low = 1) or DESC(high = 1)\n");
}

// Use variables for insert to minimize errors
// $OrderBy is the value to rank 
// $AscDesc declares which way to rank
my $FromTable = $ARGV[0];
my $ToTable   = $ARGV[1];
my $OrderBy   = $ARGV[2];
my $AscDesc   = $ARGV[3];


// DateTable is table of dates for use within the insert query. Used to loop through and rank individual days.
my $query7 = "SELECT dat FROM DateTable ORDER BY dat ASC";
my $sth7   = $dbh->prepare($query7) || carp DBI::errstr;
$sth7->execute() || carp DBI::errstr;

// Fetchrow_hashref holds all dates from date tables and while loop walks through one at a time
// The insert sorts by a value and then a row number is added to provide a rank of values
// The nested sth exists because need to reference $dateVar from fetchrow
while(my $ref = $sth7->fetchrow_hashref()) {
    my $dateVar = $ref->{dat};
    print "$dateVar \n";
    my $query6 = "INSERT INTO $ToTable 
        SELECT t.*,". '@rownum := @rownum +1' . " 
        FROM $FromTable t, ".'(SELECT @rownum := 0) r  
        WHERE dat ='."$dateVar
        ORDER BY $OrderBy $AscDesc";
    my $sth6 = $dbh->prepare($query6) || carp DBI::errstr;
    $sth6->execute() || carp DBI::errstr;
    $sth6->finish();
}

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