Многоколонное целочисленное упорядочение - PullRequest
6 голосов
/ 13 февраля 2010

Я не знаю, выбрал ли я соответствующий заголовок для этого вопроса (если нет, пожалуйста, измените его соответствующим образом), но рассмотрите следующую упрощенную структуру таблицы, с которой я работаю:

----------------------------------------------
|  date  |  i  |  j  |  k  |  x  |  y  |  z  |
----------------------------------------------
| 100209 |  1  |  2  |  3  |  4  |  5  |  6  |
----------------------------------------------
| 100210 |  2  |  3  |  4  |  5  |  6  |  7  |
----------------------------------------------
| 100211 |  0  |  1  |  2  |  3  |  4  |  5  |
----------------------------------------------
| 100212 |  1  |  2  |  3  |  4  |  5  |  6  |
----------------------------------------------
| 100213 |  6  |  5  |  4  |  3  |  2  |  1  |
----------------------------------------------

i, j, k, x, y, z - все это не связанные целые числа / числа с плавающей запятой, все они представляют различные факторы и могут иметь очень разные порядки величины ( i может варьироваться от 1 до 10, а j может варьироваться от 100 до 1000 ).

Я пытаюсь выбрать даты, которые соответствуют схожим условиям; При заданном наборе i, j, k, x, y, z мне нужно вернуть все результаты, упорядоченные по близости всех значений как например, , если i = 1, j = 2, k = 3, x = 4, y = 5 и z = 6, запрос должен вернуть следующие даты в следующем порядке:

  1. 100209
  2. 100212
  3. 100210
  4. 100211
  5. 100213

Я не уверен, относится ли это к вопросу или нет, но некоторые значения (i, j, k) означают чем больше, тем лучше , тогда как другие значения (x, y, z) означают обратное: чем меньше, тем лучше .

Как мне построить такой запрос? Возможно ли это только с помощью SQL?


@ Pentium10:

Я постараюсь ответить на ваш комментарий как можно лучше. Вот образец моих данных:

---------------------------------------------------------------------------------
  date  |  temperature  |  humidity  |  pressure  |  windSpeed  |  moonDistance  
---------------------------------------------------------------------------------
 090206 |  7            |  87        |  998.8     |  3          |  363953        
---------------------------------------------------------------------------------
 ...... |  ...          |  ...       |  ....      |  ...        |  ......        
---------------------------------------------------------------------------------
 100206 |  10           |  86        |  1024      |  2          |  386342        
---------------------------------------------------------------------------------
 100207 |  9            |  90        |  1015      |  1          |  391750        
---------------------------------------------------------------------------------
 100208 |  13           |  90        |  1005      |  2          |  396392        
---------------------------------------------------------------------------------
 100209 |  12           |  89        |  1008      |  2          |  400157        
---------------------------------------------------------------------------------
 100210 |  11           |  92        |  1007      |  3          |  403012        
---------------------------------------------------------------------------------
 100211 |  6            |  86        |  1012      |  2          |  404984        
---------------------------------------------------------------------------------
 100212 |  6            |  61        |  1010      |  3          |  406135        
---------------------------------------------------------------------------------
 100213 |  7            |  57        |  1010      |  2          |  406542        
---------------------------------------------------------------------------------

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

  1. показать мне все даты, упорядоченные по сходству условий, предоставленных мной
  2. показать мне все даты, упорядоченные по сходству условий, наблюдаемых в дате X

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

Цель состоит в том, чтобы иметь возможность достигать таких результатов:

Сегодня действительно похоже на д / м / гг, очень похоже на д / м / гг, несколько аналогично д / м / гг, ...

В моем случае я работаю с погодными и атмосферными данными, но, если это поможет, думаю, вы можете подумать об этой проблеме в терминах employees (с колонками attendance, hoursPerWeek и monthlySalary) и порядком например, сотрудниками, которые наиболее похожи на attendance = 100%, hoursPerWeek = 40 и monthlySalary = $5000.

PS: Теперь, когда я привел этот пример сотрудников, я больше не уверен, можно ли его сравнить с примером погоды, с которым я работаю, так как с таблицей сотрудников Вы можете вычислить (например, rating = monthlySalary / hoursPerWeek * attendance) и отчасти взвесить столбцы, но я не думаю, что то же самое можно сделать с таблицей погоды - вход оценивается в любом случае .

PS2 : Я не уверен, достаточно ли я выразил себя, если у вас все еще есть сомнения, пожалуйста, дайте мне знать.


Bounty

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

Ответы [ 4 ]

6 голосов
/ 15 февраля 2010

Проблема, с которой вы, похоже, сталкиваетесь, заключается в том, что каждый столбец имеет разный масштаб, и поэтому вы не можете легко объединить их. Эта проблема может быть решена с помощью техники, называемой отбеливание. Это включает в себя вычисление среднего и стандартного отклонения для каждого столбца (это можно сделать в 1 операторе SQL), а затем масштабирование каждого столбца к этому при выборе:

colSortPos = (colValue-colMean) / colStdev

Это даст вам каждый столбец в диапазоне от 0 до +/- 1 стандартного отклонения в диапазоне +/- 1. Хитрость заключается в том, чтобы объединить их так, чтобы похожие даты были вместе. Проблема здесь в том, что это не двумерная проблема, и поэтому вам нужно мыслить многомерно. Поэтому я предлагаю принять евклидово расстояние в качестве порядка сортировки.

SELECT
    date,
    i,
    j,
    k,
    SQRT( POW((i-@iMean)/@iStdDEv, 2) + POW((j-@jMean)/@jStdDEv, 2) + POW((k-@kMean)/@kStdDEv, 2) )
AS
    sort_order
FROM
    table
ORDER BY
    sort_order

Единственная проблема с этим состоит в том, что она проецирует вашу проблему на одномерное пространство, которое может заставить вас пропустить некоторые корреляции. Чтобы обойти это, я предлагаю использовать метод кластеризации, такой как K-means, который довольно прост в реализации и действительно быстр. Это позволит вам сгруппировать даты в k кластеров, которые отображают наибольшее сходство [http://en.wikipedia.org/wiki/K-means_clustering]. Если у вас есть необработанные данные и вы хотите поиграть с этими (и другими) техниками, тогда я предлагаю попробовать набор инструментов weka [http://www.cs.waikato.ac.nz/ml/weka/], который позволит вам поиграть с этими техниками.

3 голосов
/ 13 февраля 2010

Я думаю, что это возможно. Попробуйте использовать функцию, которая добавляет разницу. Например:

SELECT *, ABS (i - @i) + ABS (j - @j) + ABS (k - @k) + ABS (x - @x) + ABS (y - @y) + ABS (z - @z) ОТ стола

Это даст вам значение разницы нечеткой логики. Чем ниже, тем ближе матч. Вы также должны быть в состоянии сортировать по этому выражению: то есть, порядок по ABS (i - @i) ... ASC

Пара предложений, возможно, выберите результаты во временной таблице и отсортируйте их по этому.

В качестве альтернативы, если вы используете сервер SQL, обратите внимание на использование .NET CLR и выполняйте его в сборке .NET - это даст вам больше возможностей и возможностей. Это также позволит вам легче прикрепить дополнительный вес к определенным полям (если вы имели в виду, что некоторые поля должны иметь дополнительный вес).

Надеюсь, это поможет, Стив

1 голос
/ 17 февраля 2010

Это сложно (если не невозможно) сделать в SQL, но есть метод многомерного анализа, который называется Факторный анализ. Это способ создания «фактора» - линейной комбинации ваших переменных, которая добавляет вес каждому входу, чтобы получить «факторный балл». По сути, он выполняет ряд линейных алгебраических манипуляций с вашими данными, чтобы создать единичный набор баллов, который минимизирует некоторые цели (например, суммарные ошибки).

Я провел факторный анализ 3-х часовых данных о погоде, и он выглядит довольно неплохо. Вы можете видеть, что записи со сходными значениями коэффициентов обычно очень близки по значениям по всем четырем показателям. Я использовал извлечения главных компонентов с вращением Equimax:

Wind    Air    Dewpoint    BP         Score
-------------------------------------------
3       12     9           1012.2     -2.72
5       17     11          1011.9     -1.77
5       16     10          1010.8     -1.75
6       15     10          1010.4     -1.68
3       19     13          1012.1     -1.57
5       17     11          1010.8     -1.54
7       17     12          1012.0     -1.53
8       19     12          1012.0     -1.24
5       20     14          1012.0     -1.18
7       17     12          1009.8     -1.06
9       20     13          1012.5     -1.05
8       21     12          1012.1     -1.05
7       19     11          1009.9     -0.98
6       18     13          1009.6     -0.90
0       24     17          1012.1     -0.90
8       20     12          1010.8     -0.88
5       22     15          1012.0     -0.87
10      21     12          1012.0     -0.86
8       21     12          1010.8     -0.78
9       19     12          1010.2     -0.78
8       23     10          1010.7     -0.76
6       23     15          1012.3     -0.75
7       20     12          1009.7     -0.73
7       20     12          1009.6     -0.71
10      22     14          1011.5     -0.45
7       19     15          1009.3     -0.45
6       20     16          1009.7     -0.41
7       20     15          1009.4     -0.37
10      24     12          1010.6     -0.26
5       26     18          1012.5     -0.26
9       23     15          1011.0     -0.22
12      24     16          1012.3     -0.04
6       25     16          1009.5      0.15
5       28     20          1012.5      0.16
0       28     17          1009.0      0.16
8       24     17          1010.2      0.17
3       30     20          1012.5      0.19
12      23     16          1010.6      0.21
8       25     15          1009.5      0.21
13      25     13          1010.5      0.22
13      25     14          1010.6      0.30
5       25     20          1010.1      0.35
6       25     19          1009.9      0.37
9       23     18          1009.5      0.40
13      25     15          1010.3      0.46
5       30     21          1012.4      0.48
7       26     19          1010.0      0.54
12      27     16          1010.9      0.56
8       24     20          1009.7      0.58
7       27     17          1009.2      0.60
7       27     18          1009.6      0.62
7       27     17          1009.0      0.64
8       26     21          1010.6      0.70
9       28     17          1009.8      0.75
8       25     22          1010.0      0.82
8       26     23          1010.8      0.86
8       25     22          1009.8      0.87
8       25     23          1010.1      0.91
9       26     22          1010.5      0.91
8       26     22          1009.8      0.97
14      29     17          1010.8      1.06
12      26     22          1010.8      1.09
10      31     18          1010.3      1.14
14      30     18          1010.7      1.28
17      29     17          1010.9      1.29
10      27     22          1009.4      1.32
12      26     22          1009.7      1.32
8       27     24          1009.3      1.38
14      27     22          1010.2      1.49
12      28     22          1009.8      1.51
16      31     19          1010.7      1.66
14      28     23          1009.6      1.82
1 голос
/ 13 февраля 2010

Я не уверен, что это актуально или не к вопросу, а к некоторым ценностям (I, J, K) означает, что чем больше, тем лучше другие значения (x, y, z) означают наоборот: чем меньше, тем лучше.

Поскольку вы имеете дело с датами, вы можете получить другие даты на основе этих критериев.
Например, вы можете вычислить новые даты, для значения, имеющего higher effect, вы добавляете пару часов / дней / недель / месяцев к вашей дате, а если значение имеет lover effect, вы добавляете к своим датам только секунды / минуты. Затем вы сортируете на основе этой вычисленной новой даты.
Вы можете вычитать даты, используя отрицательные компенсации, если они достигают пикового уровня

Проверьте нечеткий SQL ( FSQL )

РЕДАКТИРОВАТЬ 1

Попробуйте: std (i) * abs (i- @ i) ...

SELECT 
  (select std(i) from fuzzysearch)*abs(i-7) as v1,
  (select std(j) from fuzzysearch)*abs(j-90) as v2,
  f.* 
FROM fuzzysearch as f 
order by 
  v1 asc, 
  v2 desc
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...