Я не знаю, выбрал ли я подходящий заголовок для этого вопроса (если нет, пожалуйста, измените его соответствующим образом), но рассмотрите следующую упрощенную структуру таблицы, с которой я работаю:
---------------------------------------------- | 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
запрос должен вернуть следующие даты в следующем порядке:
Я не уверен, относится ли это к вопросу или нет, но некоторые значения ( i
, j
, k
) означают больше, а другие значения ( x
, y
, z
) означают противоположное: меньше – лучше .
Как я должен построить такой запрос? Возможно ли это с помощью SQL?
Я постараюсь ответить на ваш комментарий наилучшим образом. Вот пример моих данных:
--------------------------------------------------------------------------------- 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 ---------------------------------------------------------------------------------
В моей структуре таблицы больше столбцов и тысяч строк, но, надеюсь, этого будет достаточно, чтобы понять мою точку зрения. Я не буду пытаться упорядочить эти значения, как это было в предыдущем примере, потому что я, вероятно, ошибаюсь, но мне в основном нужно делать два типа запросов с этими данными:
Я понимаю, что второй запрос можно легко архивировать, используя первый, но моя проблема заключается в сортировке по сходству с использованием нескольких столбцов, вот что я имел в виду под « упорядочением по близости всех значений в целом ». Как и в случае, если я имел дело только с одним столбцом, было бы намного проще заказать по подобию, но моя голова действительно начинает вращаться при работе с несколькими столбцами.
Цель состоит в том, чтобы иметь возможность производить такие результаты:
Сегодня он действительно похож на 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