2009-12-30 3 views
0

Я читаю книгу, в которой автор говорит о том, чтобы вывести строку + все связанные родительские строки за один шаг. Как и выбор заказа + все его предметы сразу. Хорошо, звучит неплохо, но на самом деле: я никогда не видел возможности в SQL, чтобы спросить - скажем - один заказ + 100 пунктов? Как будет выглядеть этот набор записей? Получаю ли я 101 строку с объединенными полями как в порядке, так и в таблице элементов, где 100 строк имеют много значений NULL для полей заказа, а одна строка имеет много значений NULL для полей элемента? Это путь? Или есть что-то намного круче? Я имею в виду ... Я никогда не слышал о том, чтобы набирать массивы на поле?Как получить граф объекта сразу?

ответ

3

простое соединение будет делать трюк:

SELECT  o.* 
,   i.* 
FROM  orders o 
INNER JOIN order_items i 
ON   o.id = i.order_id 

будет возвращать одну строку для каждой строки в ORDER_ITEMS. Возвращенные строки состоят из всех полей из таблицы заказов и объединены с этим, все поля из таблицы order_items (буквально, записи из таблиц объединены, то есть они объединяются путем записи конкатенации)

So если у заказов есть (id, order_date, customer_id) и order_items (order_id, product_id, price), результат вышеуказанного заявления будет состоять из записей с (id, order_date, customer_id, order_id, product_id, price)

Одна вещь вам нужно знать, что этот подход ломается всякий раз, когда для одного «хозяина» есть две разные «детализированные» таблицы. Позволь мне объяснить.

В примере orders/order_items заказы - это master и order_items - это деталь: каждая строка в order_items принадлежит или зависит только от одной строки в заказах. Обратное неверно: одна строка в таблице заказов может иметь нулевые или более связанные строки в таблице order_items. Условие соединения

ON o.id = i.order_id 

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

Теперь предположим, что у вас есть один мастер с двумя деталями, например, клиентами как master и customer_orders как detail1 и customer_phone_numbers. Предположим, вы хотите получить конкретный клиент вместе со всеми заказами и всеми его номерами телефонов. Можно было бы попытаться написать:

SELECT  c.*, o.*, p.* 
FROM  customers    c 
INNER JOIN customer_orders   o 
ON   c.id     = o.customer_id 
INNER JOIN customer_phone_numbers p 
ON   c.id     = p.customer_id 

Это действительно SQL, и он будет выполнять (asuming таблицы и имена столбцов на месте) Но проблема в том, что это даст вам результат мусора. Если у вас есть на клиенте с двумя заказами (1,2) и два номера телефона (A, B), вы получите эти записи:

customer-data | order 1 | phone A 
customer-data | order 2 | phone A 
customer-data | order 1 | phone B 
customer-data | order 2 | phone B 

Это мусор, как это предполагает, что есть определенная взаимосвязь между порядка 1 и телефоном номера A и B, а также порядок 2 и номера телефонов A и B.

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

Итак, JOIN отлично подходит для «сглаживания» иерархии элементов известной глубины (customer -> orders -> order_items) в одну большую таблицу, которая только дублирует основные элементы для каждого элемента детализации. Но ужасно извлечь истинный график связанных элементов. Это прямое следствие того, как SQL разработан - он может выводить только нормализованные таблицы без повторяющихся групп. Это способ отображения объектных реляционных карт, позволяющий определять определения объектов, которые могут хранить и извлекать несколько зависимых коллекций подчиненных объектов из реляционной базы данных, не теряя при этом зрелости в качестве программиста.

1

Это обычно делается с помощью предложения JOIN. Это не приведет к множеству значений NULL, но многие повторяющиеся значения для родительской строки.

Другой вариант, если ваша база данных и язык программирования поддерживают его, он возвращает оба набора результатов в одном соединении - один выбирает для родительской строки другую для связанных строк.

Смежные вопросы