Реляционная модель и запросы, которые естественным образом возвращают повторяющиеся строки - PullRequest
0 голосов
/ 08 октября 2010

Обычно считается, что в реляционной модели:

  1. Каждая реляционная операция должна давать отношение.
  2. Отношения, будучи наборами, не могут содержать повторяющиеся строки.

Представьте себе отношение «ПОЛЬЗОВАТЕЛИ», которое содержит следующие данные.

ID FIRST_NAME LAST_NAME
 1 Mark       Stone
 2 Jane       Stone
 3 Michael    Stone

Если кто-то выполнит запрос select LAST_NAME from USERS, типичная база данных вернется:

LAST_NAME
Stone
Stone
Stone

Сэто не отношение - поскольку оно содержит повторяющиеся строки - что должна вернуть идеальная СУБД?

Ответы [ 5 ]

3 голосов
/ 11 октября 2010

"Но некоторая информация потеряна - что есть 3 пользователя с этой фамилией."

Если вас интересует количество пользователей с таким именем, тогда запрос вашего примера невопрос, который вы должны задать.

Запрос вашего примера даст ответ на вопрос «Каковы все фамилии, так что существует пользователь с такой фамилией?».

Если вопрос, который вы хотите задать, это «сколько пользователей с именем« Камень »», то запрос, который вы должны отправить, - «Выбрать количество (...) пользователей, где last_name =« Камень »;

Проекция всегда «теряет» информацию.Информация, которая связана с атрибутами, которые проецируются.Я не понимаю, как известное свойство полезного реляционного оператора можно объяснить как аргумент против этого оператора.

2 голосов
/ 08 октября 2010

В СУБД реляционная проекция только на столбец с фамилией вернет только набор кортежей с различными значениями фамилии. Там не будет повторяющихся кортежей.

В SQL верно, что вы получите дубликаты, если вы не укажете ключевое слово DISTINCT. Это потому, что SQL не является по-настоящему реляционным языком - среди прочего, потому что таблицы SQL и выражения таблиц не являются правильными отношениями. СУБД SQL не является СУБД.

2 голосов
/ 09 октября 2010

"что должна вернуть идеальная СУБД?"

Как указал Дэвид, она должна возвратить (в вашем примере) одну строку.

СУБД SQL является только реляционной, если онаобрабатывает каждый SELECT, как если бы запросили SELECT DISTINCT.(Но есть несколько крошечных дополнительных условий, которые также должны быть выполнены.)

Причина этого в том, что «значение» этой единственной строки таково: «Существует такой пользователь, что у него естьfirst_name, у него есть ID, а его last_name - «Камень».

Нет никакой логической необходимости повторять это утверждение во второй раз.Авторитетное упоминание, о котором вы просили, - это сам Тед Кодд: «Если что-то является правдой, то повторение этого дважды не сделает его более правдивым».

1 голос
/ 08 октября 2010

Я не уверен, что вижу проблему с возвращаемыми значениями. Есть три записи, которые содержат «Камень» для LAST_NAME. Это было бы очевидно, если бы в запрос были включены FIRST_NAME или ID, но это не так. Обычно ключевое слово DISTINCT используется для обработки этого и обеспечения отсутствия дубликатов.

На самом деле, если бы моя база данных начала применять DISTINCT автоматически (что звучит так, как вы думаете, возможно, и должно быть), я был бы несколько раздражен. Просмотр дублирующихся строк, когда вы этого не ожидаете, часто является необходимым разрывом при отладке некоторых странных проблем с данными в базе данных.

0 голосов
/ 08 марта 2014

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

Чтобы перевести ваш запрос:

выберите LAST_NAMEот ПОЛЬЗОВАТЕЛЕЙ

на английский, это будет:

"скажи мне фамилию всех пользователей"

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

Если бы вы хотели задать вопрос: «Каковы разные фамилии учеников в классе», он быНе перечисляйте дублирующиеся имена.Однако это то, для чего существует ключевое слово «DISTINCT».

Таким образом, запрос будет:

выбрать отдельное LAST_NAME из USERS

И если вас действительно интересует количествоуникальные фамилии на английском языке: «Сколько разных фамилий у учеников в классе» или, используя ваш пример:

выберите количество (отличное LAST_NAME) из USERS

, тогда как: выберите количество(LAST_NAME) от USERS

будет означать по-английски: «Сколько человек в классе имеет фамилию?»

...