Схема базы данных для поиска моих возрастных групп - PullRequest
2 голосов
/ 09 декабря 2011

Я некоторое время боролся с этим, пытаясь понять, как сделать это наиболее эффективно.

Проблема заключается в следующем. У меня есть элементы в базе данных, которые нужно продавать для определенных возрастных групп, таких как ages 10 to 20 или ages 16+, и мне нужно иметь возможность сделать запрос, например, find item that is for 17 year old

Вот мои две лучшие идеи (но мне они тоже не нравятся, так как я думаю, что они обе неэффективны).

  1. Имеет столбец csv со значениями, такими как 10-20 и 16+, извлекает весь список и анализирует его (хотя я знаю, что у меня нет идей),

  2. Имеет столбец csv со значениями, такими как 10,11,12,13...20 для диапазонов, так что я могу искать его, используя WHERE ages LIKE "%17%", а для случаев, подобных 16+, мне пришлось бы извлекать эти особые случаи, используя что-то вроде WHERE ages LIKE "%+%" и разбери их.

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

Есть ли лучший способ? Если нет, как вы думаете, вы могли бы сделать любую из моих моделей более эффективной? Спасибо.

Ответы [ 4 ]

3 голосов
/ 09 декабря 2011

Вы можете сделать это так:

  1. Добавьте в таблицу lower_age и upper_age столбцы, оба целых числа, допускающие значения NULL.
  2. Если lower_age равно NULL, то нижней границы нет.
  3. Если upper_age равно NULL, то верхней границы нет.
  4. Объедините COALESCE и BETWEEN для ваших запросов.

Чтобы уточнить (4), вы хотите сказать что-то вроде этого:

select *
from your_table
where $n between coalesce(lower_age, $n) and coalesce(upper_age, $n)

где $n - это возраст, который вы ищете. МЕЖДУ использует включающие границы, поэтому coalesce(lower_age, $n) игнорирует $n, если lower_age не равно NULL, и дает вам $n >= $n (то есть автоматическое значение true на этой границе), если lower_age равно NULL; аналогично для upper_age.

Если что-то подходит только для 11-летних, тогда ваш [lower_age,upper_age] закрытый интервал будет [11, 11], 16+ будет [16, NULL], шесть и ниже будут [NULL, 6], каждый будет [NULL, NULL], и никто не получит [23, 11] или что-либо еще с lower_age > upper_age (или, что более вероятно, с недопустимыми данными, из-за которых ограничение CHECK может привести к шипящему совпадению).

1 голос
/ 09 декабря 2011

У вас есть несколько вариантов (без каламбура). Для рекомендаций по возрасту самый простой способ - сохранить min_age и max_age и выполнить запрос следующим образом:

select * from item where :age between min_age and max_age

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

В качестве альтернативы вы можете использовать таблицу m: n

create table item_ages (item_id int not null, age int not null, constraint item_ages_pk primary key (item_id, age)

и заполните его явными значениями:

item_id | age
-------------
      1 | 16
      1 | 17
      1 | 18

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

Обратите внимание, что ответ CBRRacer имеет схожие свойства: оба разделяют идею о том, что вы готовите структуру данных, которую можно легко проиндексировать, и отвечаете на вопрос фильтра из этого индекса. Это популярный метод хранения маркетинговых данных в приложениях электронной коммерции. Крайним концом этого диапазона будет использование специального пакета для хранения инвертированных индексов для этой цели. Но для простой рекомендации по возрасту это, конечно, излишне.

1 голос
/ 09 декабря 2011

Вы можете сделать это несколькими способами. Если вы храните возраст пользователя (независимо от того) в строке. Затем вы можете запросить возраст и с> 16 или <30 или между 10-20 независимо от. Другой вариант - сохранить это как побитовое. Имейте справочную таблицу и сохраняйте ваши различные диапазоны, если они могут иметь кратные значения, тогда вы просто добавляете два значения строки вместе. </p>

1 = 10
2 = 16+
4 = 10-20
8 = 20-30
16 = 20+
32 = 30+
.
.
.
.

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

Table of Users
ID     Name        BitWise
 1     test          2
 2     something     6 (2+4)
 3     blah          24 (8+16)

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

0 голосов
/ 09 декабря 2011

Примерно так:

SELECT *
  FROM tablename
 WHERE 17 BETWEEN start_age AND end_age
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...