Как я могу запросить денормализованную таблицу и получить связанные данные в наборе результатов?

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

Книжный стол

ID, Title, Author-Name, Publisher-Name, Category

В другой таблице у меня есть что-то вроде следующего:

Таблица авторов

ID, Author-Name, Address

Таблица издателя

ID, Publisher-Name, Address

Предположим, что Publisher-Name и Author-Name всегда уникальны.

Желаемый результат

Теперь все, что мне нужно сделать, это создать запрос, который создает набор результатов, который включает:

 1. all columns from Book table
 2. Author.ID 
 3. Publisher.ID

Окончательный набор результатов будет выглядеть примерно так:

Столбцы набора результатов

ID, Title, Author-Name, Author.ID as [AuthorID], Publisher-Name, Publisher.ID as [PublisherID] Category

Допустим, в таблице книг есть две строки, тогда набор результатов будет иметь две строки, которые включают соответствующие значения для Author.ID и Publisher.ID, потому что поиск был выполнен в запросе и возвращен в результате - установленный.

Что я пробовал: присоединяйтесь

Я пробовал использовать различные соединения, но всегда получаю more rows than just two rows, потому что соединение, кажется, присоединяется к Publisher.ID И Author.ID, а я get 1 row для каждого из них, что в итоге дает мне строки 4 вместо 2.

Образец данных

Книги

1, 'All The Time', 'Fred Smith', 'Big Pub Co.', 'non-fiction'
2, 'Biggest Title Ever', 'John Jones', 'Small Pub Co.', 'fiction'

Авторы

100, 'Fred Smith', 'Yukon, AK'
101, 'John Jones', 'Happy, VT'

Издатели

300, 'Big Pub Co', 'Angry, IL'
301, 'Small Pub Co', 'Someplace, IN'

Ожидаемый результат

1, 'All The Time', 'Fred Smith', 100, 'Big Pub Co.', 300, 'non-fiction'
2, 'Biggest Title Ever', 'John Jones', 101, 'Small Pub Co.' 301, 'fiction'

Не могли бы вы предоставить образцы данных и ожидать результата? это действительно поможет

D-Shih 31.10.2018 14:01

Поделитесь своим запросом, где вы использовали join.

Mayank Porwal 31.10.2018 14:08

@ D-Shih Добавлены образцы данных.

raddevus 31.10.2018 14:10

отсутствуют точки в Publisher?

pi.314 31.10.2018 14:11

Если он еще не существует, вы должны создать ассоциативную таблицу между книгами и авторами, в случае, если существуют 2 автора с одинаковым именем, такие же сделки с издателями.

user2366842 31.10.2018 14:51

Для запроса ограничений не требуется. Уровень нормализации значения не имеет. Что необходимо и достаточно, так это то, что означают таблицы. Вы не четко описываете, какие строки вы хотите получить в результате. Например, разговоры о «поиске» расплывчаты. Скажите, какие строки входят в ваши базовые таблицы с точки зрения бизнес-ситуации. Затем скажите, какие строки входят в результат вашего запроса с точки зрения бизнес-ситуации и / или базовых таблиц. PS Пожалуйста, отформатируйте свои таблицы заголовками. См. минимальный воспроизводимый пример. Есть ли какое-нибудь практическое правило для построения SQL-запроса из понятного человеку описания?

philipxy 31.10.2018 20:10

@philipxy подождите, вы видели раздел ожидаемых результатов? Я описал все данные. Спасибо за вашу помощь.

raddevus 31.10.2018 20:28

Здесь простейшие предположения по именам столбцов также являются значениями базовых таблиц и таблиц запросов, потому что ваш запрос очень прост. Но вы действительно не можете четко описать свой результат в тексте - ваш текст нечеткий и ничего не добавляет к предположениям по именам столбцов. В моем комментарии упомянуты оба этих аспекта - значения и примеры - когда я говорил, как составить / передать спецификацию запроса в целом. Это будет иметь значение, если ваш запрос не является почти тривиальным. Если вы заметили, что пишете «что-то вроде», это означает, что вы знаете, что не внесли ясности.

philipxy 31.10.2018 21:28
0
8
76
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Вы можете попробовать JOIN` и получить нужные столбцы из этих таблиц.

SELECT 
    b.ID, 
    b.Title,
    b.[Author-Name],
    a.id,
    p.[Publisher-Name],
    p.id,b.Category
FROM Book b 
JOIN Author a on b.[Author-Name] = a.[Author-Name]
JOIN  Publisher p ON b.[Publisher-Name] = p.[Publisher-Name]

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

user2366842 31.10.2018 14:53

@ user2366842 Очень хорошее замечание. Похоже, у меня было две проблемы, одна из которых заключалась в том, что в таблицах издателя и автора были повторяющиеся данные, из-за которых в исходном запросе возвращалось несколько строк.

raddevus 31.10.2018 15:12

@raddevus Не могли бы вы предоставить больше образцов данных и ожидать результата, позвольте мне разобраться в проблеме :)

D-Shih 31.10.2018 15:15

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

raddevus 31.10.2018 15:20

Извините, что вы имеете ввиду? потому что он работает в sqlfiddle из ваших данных samlpe dbfiddle.uk/…

D-Shih 31.10.2018 15:26

Вместо Inner я бы посоветовал вам покинуть соединение на случай, если между таблицами не будет совпадений.

SELECT
    ...
FROM
    BookTable BOOK
    LEFT JOIN
    AuthorTable AT
        ON AT.Author-Name = BOOK.Author-Name
    LEFT JOIN
    PublisherTable PT
        ON PT.Publisher-Name = BOOK.Publisher-Name

Однако убедитесь, что ваши строки из Book Table не будут умножаться: используйте external apply:

SELECT
    BOOK.ID,
    BOOK.Title,
    BOOK.Author-Name,
    AT.ID AS AuthorID,
    BOOK.Publisher-Name,
    PT.ID AS PublisherID,
    BOOK.Category
FROM
    BookTable BOOK
    OUTER APPLY (SELECT TOP 1 ID FROM AuthorTable AT WHERE AT.Author-Name = BOOK.Author-Name) AT
    OUTER APPLY (SELECT TOP 1 ID FROM PublisherTable PT WHERE PT.Publisher-Name = BOOK.Publisher-Name) PT

Итак, несколько вещей:

  1. Ваши данные не денормализованы, они (правильно) нормализованы.
  2. Вы приняли странное решение сохранить автора имя и издателя имя в таблице книг. Это вызовет проблемы, если у вас есть два автора или издателя с одинаковыми именами в своих таблицах. Если этого никогда не произойдет (то есть вам потребуется вариант имени в случае одноименных авторов или издателей), вы можете избавиться от столбца идентификаторов в их соответствующих таблицах.
  3. Решение вашей проблемы - использовать JOIN, как вы сделали вывод, но мы не можем сказать, где вы допустили ошибку, потому что вы не показал то, что вы пробовали.

Все это похоже на то, что вы случайно выполнили декартово соединение JOIN, при котором вы объединяете несколько таблиц, но не можете предоставить условие присоединения.

Итак, я подозреваю, что вы написали что-то вроде (есть разные способы выразить это):

FROM Books JOIN Authors JOIN Publishers

и вы должны были написать:

FROM Books INNER JOIN Authors ON Books.Author-Name = Authors.Author-Name
   INNER JOIN Publishers ON Books.Publisher-Name = Authors.Publisher-Name

Очень хорошая "лишняя" информация. И вы правы, я сделал первое соединение (без внутреннего), я попробую второе (с внутренним) и дам вам знать.

raddevus 31.10.2018 14:42

«Нормализованный» имеет два широких значения - нормализованный к некоторому «1NF» (который сам по себе не имеет фиксированного значения) и нормализация к более высоким NF. Очевидно, вы не имеете в виду последнее в своей первой пуле, потому что это противоречило бы вашей второй пуле. Но, по-видимому, это то, что имел в виду @raddevus, когда они его использовали.

philipxy 31.10.2018 20:19

@philipxy Мое использование denormalized относилось к строковым значениям, которые копируются в таблицу Book для имени автора и издателя, вместо того, чтобы зависеть от author.Id publisher.id и заставлять выполнять другой поиск. Это была вольная интерпретация денормализации в основном в попытке указать на странность имени автора / имени издателя. Причина появления этих данных в реальном решении заключается в том, что служба может выполнить один запрос к таблице Book и получить необходимую информацию без дополнительного запроса или соединения. Спасибо

raddevus 31.10.2018 20:26

@raddevus Спасибо. Более полезно всегда прилагать усилия, чтобы сказать то, что вы имеете в виду, вместо того, чтобы писать что-то, что не говорит о том, что вы имеете в виду. (См. Мой последний комментарий к вопросу.)

philipxy 31.10.2018 21:41

Другие вопросы по теме