Соответствующая структура данных для таблицы, которая использует диапазоны

В целом (я не использую mssql, так не может прокомментировать конкретно), первичные ключи делают хорошие индексы. Они уникальны и должны были определить значение. (Кроме того, первичные ключи делают такие хорошие индексы, что им обычно создавали индекс автоматически.)

индекс является эффективно копией столбца, который был отсортирован для разрешения двоичного поиска (который намного быстрее, чем линейный поиск). Системы баз данных могут использовать различные приемы для ускорения поиска еще больше, особенно если данные более сложны, чем простое число.

Мое предложение не должно было бы использовать индексы первоначально и представить Ваши запросы. Если особый запрос (такой как поиск людей фамилией, например) выполняется очень часто, попытайтесь создать индекс по атрибутам relevate и профилю снова. Если существует значимое ускорение на запросах и незначительное замедление на вставках и обновления, сохраните индекс.

(Извинения, если я повторяю материал, упомянутый в Вашем другом вопросе, я не столкнулся с ним ранее.)

5
задан Jon 14 December 2009 в 19:27
поделиться

6 ответов

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

$fp = fopen('data.csv', 'r');
$cols = fgetcsv($fp);
array_shift($cols); // remove empty first item
$data = array();
while ($row = fgetcsv($fp)) {
  list($min, $max) = explode('-', $row[0]);
  // TODO: Handle non-range values here (e.g. column header "<22")
  $data["$min-$max"] = array();
  for ($x = 0; $x < count($cols); $x++) {
    $data["$min-$max"][$cols[$x]] = $row[$x + 1];
  }
}

Затем вам нужно будет добавить логику синтаксического анализа в свою функцию поиска :

function lookup($row, $col) {
  $return = null;
  // Loop through all rows
  foreach ($data as $row_name => $cols) {
    list($min, $max) = explode('-', $row_name);
    if ($min <= $row && $max >= $row) {
      // If row matches, loop through columns
      foreach ($cols as $col_name => $value) {
        // TODO: Add support for "<22"
        list($min, $max) = explode('-', $col_name);
        if ($min <= $col && $max >= $col) {
          $return = $value;
          break;
        }
      }
      break;
    }
  }
  return $return;
}
2
ответ дан 15 December 2019 в 01:03
поделиться

Структура базы данных:

values
------
value
x_range_start
x_range_end
y_range_start
y_range_end

Код:

function lookup(x, y) {
    sql = "
        SELECT * FROM values
        WHERE
            x >= x_range_start
            AND
            x <= x_range_end

            AND
            y >= y_range_start
            AND
            y <= y_range_end
    "

    /---/
}

Ваши данные будут отображаться в базе данных следующим образом:

      <22  23-27   
8-10   1.3   1.8
11-13  2.2   2.8
14-16  3.2   3.8

(value, x start, x end, y start, y end)
1.3, 0, 22, 8, 10
1.8, 23, 27, 8, 10
2.2, 0, 22, 11, 13
...

В основном хранятся начальные и конечные числа осей x и y для каждого значения в таблице.

1
ответ дан 15 December 2019 в 01:03
поделиться

Я неравнодушен к 2-мерному массиву с "хеш-функцией", которая отображает диапазоны в определенные адреса в таблица.

Итак, ваша основная структура данных будет двумерным массивом:

    0     1   
0  1.3   1.8
1  2.2   2.8
2  3.2   3.8

Затем вы должны написать две функции:

int xhash(int);
int yhash(int);

, которые принимают исходные аргументы и преобразуют их в индексы в ваш массив. Таким образом, xhash выполняет преобразование:

8-10    0
11-13   1
14-16   2

Наконец, ваша операция поиска становится.

function lookup($x, $y)
{
  $xIndex = xhash($x);
  $yIndex = yhash($y);
  // Handle invalid indices!

  return $data[$xIndex][$yIndex];
}
0
ответ дан 15 December 2019 в 01:03
поделиться

Ну, все остальные ответы используют 2D-массивы, что означает использование 2D-цикла для его извлечения. Что, если ваши диапазоны - это возрастные диапазоны или что-то подобное, может быть конечным (их так много!), А не проблемой (какие несколько сотен итераций?). Если ожидается, что ваши диапазоны будут масштабироваться до огромных чисел, игра на хеш-карте может быть вашим лучшим выбором. Итак, вы создаете хэш-функцию, которая превращает любое число в соответствующий диапазон, а затем выполняете прямой поиск вместо цикла. Это был бы доступ O (1) вместо O (n ^ 2).

Итак, ваша хеш-функция может быть такой: function hash (n) {if (n <22) return 1; если (n <25) вернуть 2; возврат -1; }, а затем вы можете указать свои диапазоны в терминах этих хеш-значений (1, 2 и т. д.), а затем просто перейти к $ data [hash (11)] [hash (25)]

0
ответ дан 15 December 2019 в 01:03
поделиться

Как насчет какой-то двумерной структуры данных.

X "coordinates" being <22, 23-27
Y "coordinates" being ...

Двумерный массив, вероятно, подойдет для этой цели.

Затем вам понадобится какая-то функция для сопоставления определенных значений X и Y с диапазонами, но это не должно быть слишком сложно.

1
ответ дан 15 December 2019 в 01:03
поделиться

Самый простой вариант: создать массив массивов, каждый из которых состоит из 5 элементов: minX, maxX, minY, maxY, value, в вашем случае было бы

$data = array(
      array(8, 10, 0, 22, 1.3),
      array(8, 10, 23, 27, 1.8),
      array(11, 13, 0, 22, 2.2), etc

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

 function find($x, $y) {
      foreach($data as $e) {
         if($x <= $e[0] && $x >= $e[1] && $y <= $e[2] && $y >= $e[3])
              return $e[4];
 }

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

создать массив массивов, где каждый массив состоит из 5 элементов: minX, maxX, minY, maxY, value, в вашем случае было бы

$data = array(
      array(8, 10, 0, 22, 1.3),
      array(8, 10, 23, 27, 1.8),
      array(11, 13, 0, 22, 2.2), etc

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

 function find($x, $y) {
      foreach($data as $e) {
         if($x <= $e[0] && $x >= $e[1] && $y <= $e[2] && $y >= $e[3])
              return $e[4];
 }

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

создать массив массивов, где каждый массив состоит из 5 элементов: minX, maxX, minY, maxY, value, в вашем случае было бы

$data = array(
      array(8, 10, 0, 22, 1.3),
      array(8, 10, 23, 27, 1.8),
      array(11, 13, 0, 22, 2.2), etc

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

 function find($x, $y) {
      foreach($data as $e) {
         if($x <= $e[0] && $x >= $e[1] && $y <= $e[2] && $y >= $e[3])
              return $e[4];
 }

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

0
ответ дан 15 December 2019 в 01:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: