MySQL рейтинг по значению за каждый день - PullRequest
2 голосов
/ 05 ноября 2010

Я пытаюсь ранжировать по% возврата за каждый день по 700 символам.

Например:

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

примерно 700 таких записей на дату 1100101

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

около 700 таких записей на дату 1100102

Я пытаюсь создать запрос или хранимую процедуру для циклического прохождения каждого дня, а затем ранжировать и вставить значение ранга для процента возвратаза каждый символ в течение каждого дня.

Я хотел бы вставить значения рангов для ранжирования процентов по возрастанию и по убыванию.

Пример таблицы, состоящей всего из 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

Ответы [ 3 ]

1 голос
/ 05 ноября 2010

Вы можете использовать этот синтаксис для выбора номера строки в вашем выборе:

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;

Чтобы получить возрастающие значения, затем обновите ту же таблицу с аналогичным запросом, чтобы получить убывающие значения.

0 голосов
/ 07 ноября 2010

Ниже показано, как я расширил пример Брента с 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();
0 голосов
/ 06 ноября 2010

Это типичная проблема внутригрупповых агрегатов , которая решается с помощью левого самоисключающего соединения .

Вам не нужны никакие хранимые процедуры для получения желаемых результатов, достаточно простого запроса 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);

Вот запрос для вычисления рангов (извините за неправильное форматирование, я не мог заставить его правильно отображаться внутри тегов <pre>):

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 ;

Обратите внимание, что этот запрос будет возвращать действительные ранги, только если у вас нет дубликатов символов на указанную дату. Вот почему я создал таблицу shuffled_symbols с PRIMARY KEY (dat ,symbol).

В таблице 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)                                
...