Многоколоночное целое упорядочение

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

---------------------------------------------- | 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 – все несвязанные целые числа / float, все они представляют разные факторы и могут иметь очень разные порядки ( 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

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

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

Сегодня он действительно похож на d / m / yy, очень похожий на d / m / yy, несколько похожий на d / m / yy, …

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

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

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


премия

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

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

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

SELECT *, ABS (i – @i) + ABS (j – @j) + ABS (k – @k) + ABS (x – @x) + ABS (y – @y) + ABS (z – @z) FROM table

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

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

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

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

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

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

Проверьте Fuzzy 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 

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

Я сделал факторный анализ по 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