MySQL View: объединение таблиц без дублирования данных в каждой строке? - PullRequest
0 голосов
/ 12 марта 2012

У меня в основном та же проблема, что и здесь:

Представление SQL: объединять таблицы, не вызывая дублирования данных в каждой строке?

За исключением этого вопроса, он использовал SQL, а я использую mysql. Мне интересно, если такой же запрос возможен в MySQL. Если да, возможно, у меня неправильный синтаксис?

Я пытаюсь сделать что-то вроде

select a.name as account_Name, 
   p.description as property_DESCRIPTION, 
   p.address as property_ADDRESS, 
   null as vehicles_DESCRIPTION,
   null as vehicles_MAKE, 
   null as vehicles_MODEL
from Accounts a
    inner join Properties p
        on a.accountid = p.accountid
UNION ALL   
select a.name as account_Name, 
   null as property_DESCRIPTION, 
   null as property_ADDRESS, 
   v.description as vehicles_DESCRIPTION,
   v.make as vehicles_MAKE, 
   v.model as vehicles_MODEL
from Accounts a
    inner join vehicles v
        on a.accountid = v.accountid

Вот мой фактический код:

SELECT user.first_name, user.last_name, upi.image_id, NULL AS friends.friend_user_id FROM user 
INNER JOIN user_profile_images as upi ON (user.user_id = upi.user_id) 
UNION 
SELECT user.first_name, user.last_name, NULL AS upi.image_id, friends.friend_user_id FROM user 
INNER JOIN friends ON (user.user_id = friends.user_id) 
WHERE user.user_id = '$profile_id'

где у меня есть 3 таблицы: user, user_profile_images и friends. И user_profile_images, и друзья связаны с пользователем через user_id. Таким образом, пользователь может иметь несколько изображений профиля, а также несколько записей друзей. Я могу опубликовать таблицы диаграмм, если это не имеет смысла. Но то, что я хочу, это в основном просмотр всей информации с полями NULL, если они не применяются к общему виду.

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

Ответы [ 2 ]

1 голос
/ 12 марта 2012

Решение, как предлагает @MarcB, заключается в использовании UNION вместо UNION ALL.

Однако у меня к вам вопрос - зачем вообще использовать UNION?Следующее эквивалентно, за исключением , что, если (скажем) учетная запись 1 имеет одно свойство и одно транспортное средство, вместо получения:

account_Name   property_DESCRIPTION   vehicles_MAKE
  account1          property1             NULL
  account1           NULL                vehicle1

Вы получите

account_Name   property_DESCRIPTION   vehicles_MAKE
  account1          property1            vehicle1

Запрос:

SELECT a.name as account_Name, 
   p.description as property_DESCRIPTION, 
   p.address as property_ADDRESS, 
   v.description as vehicles_DESCRIPTION,
   v.make as vehicles_MAKE, 
   v.model as vehicles_MODEL
FROM Accounts a
LEFT JOIN Properties p
        on a.accountid = p.accountid
LEFT JOIN vehicles v
        on a.accountid = v.accountid
WHERE p.description IS NOT NULL AND v.make IS NOT NULL

Примечание. Последняя строка (НЕТ НЕДЕЙСТВИТЕЛЬНО как для p, так и для v) имитирует часть «таблицы счетов» в INNER JOIN и обеспечивает, чтобы только учетные записи имели как минимумимущество ИЛИ транспортное средство показаны.Замените id столбцы p и v там.

0 голосов
/ 12 марта 2012

Если бы я искал такие данные, когда две таблицы связаны идентификатором третьей, я бы подумал об использовании внешних объединений.В комментариях к вопросу, на который вы ссылались, внешние объединения упоминались как возможное решение.Код для этого будет выглядеть следующим образом.

select a.name as account_Name, 
p.description as property_DESCRIPTION,
p.address as property_ADDRESS,
v.description as vehicles_DESCRIPTION,
v.make as vehicles_MAKE, 
v.model as vehicles_MODEL
from accounts a
left outer join properties p on p.accountid = a.accountid
left outer join vehicles v on v.accountid = a.accountid;

Вот как тестировалось решение.Сначала я создал три таблицы.

CREATE TABLE `accounts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

CREATE TABLE `properties` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`accountid` int(11) NOT NULL,
`description` varchar(255) COLLATE utf8_bin NOT NULL,
`address` varchar(255) COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

CREATE TABLE `vehicles` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`accountid` int(11) NOT NULL,
`description` varchar(255) COLLATE utf8_bin NOT NULL,
`make` varchar(100) COLLATE utf8_bin NOT NULL,
`model` varchar(100) COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

Затем я вставил данные в каждую таблицу.

INSERT INTO `demo`.`accounts` (
`accountid` ,
`name`
)
VALUES (
NULL , 'techport80.com'
);

INSERT INTO `demo`.`properties` (
`id` ,
`accountid` ,
`description` ,
`address`
)
VALUES (
NULL , '1', 'office', '123 may street');

INSERT INTO `demo`.`vehicles` (
`id` ,
`accountid` ,
`description` ,
`make` ,
`model`
)
VALUES (
NULL , '1', 'motorcycle', 'honda', 'shadow'
);

На этом этапе, если я протестирую решение, я получу одну строку с учетной записью,информация о собственности и транспортном средстве.

INSERT INTO `demo`.`vehicles` (
`id` ,
`accountid` ,
`description` ,
`make` ,
`model`
)
VALUES (
NULL , '1', 'passenger car', 'Ford', 'Mustang'
);

Теперь, если я проверяю свое решение, я вижу 2 ряда, по одному на каждое транспортное средство.Но два ряда не совсем дублируют.Хотя есть некоторые столбцы с теми же данными.В частности, информация об учетной записи.

INSERT INTO `demo`.`properties` (
`id` ,
`accountid` ,
`description` ,
`address`
)
VALUES (
NULL , '1', 'home', '321 yam street'
);

Затем я добавил второй адрес.Теперь четыре строки возвращены.Один для каждого транспортного средства и один для каждого адреса.Но все же, ни один из рядов не является дубликатом.

Наконец я добавил еще один автомобиль.Это должно было вызвать несбалансированность автомобиля и его свойств.

INSERT INTO `demo`.`vehicles` (
`id` ,
`accountid` ,
`description` ,
`make` ,
`model`
)
VALUES (
NULL , '1', 'Van', 'Chev', 'Cargo'
);

Теперь у нас есть 6 строк.Один на каждое транспортное средство и каждое транспортное средство также связано с двумя свойствами.(То есть 2 x 3)

Пройдя через это упражнение, мне интересно, будет ли иерархическое представление данных лучшей моделью для этих данных.Возможно, XML или JSON могут быть использованы для представления данных.Для этой задачи вы могли бы использовать хранимую функцию, но я лично сначала рассмотрел бы язык программирования, такой как PHP, C #, C ++ или множество других.

HTH

...