Как объединить результаты из нескольких таблиц с разными колонками?
у меня есть несколько таблиц с разными номерами и типами столбцов и один общий столбец.
+--------+---------+------------+-------------+
| person | beardID | beardStyle | beardLength |
+--------+---------+------------+-------------+
+--------+-------------+----------------+
| person | moustacheID | moustacheStyle |
+--------+-------------+----------------+
Я хочу получить все результаты, которые соответствуют заданному значению общего столбца. Я могу сделать это, используя несколько операторов select, таких как:
SELECT * FROM beards WHERE person = "bob"
и
SELECT * FROM moustaches WHERE person = "bob"
но для этого требуется несколько вызовов mysql API, что кажется неэффективным. Я надеялся, что смогу использовать UNION ALL для получения всех результатов в одном вызове API, но UNION требует что таблицы имеют одинаковое количество и одинаковый тип столбцов. Я мог бы написать инструкцию SELECT, которая вручную добавит результаты из каждой таблицы, добавив столбцы со значениями NULL, но это быстро станет неуправляемым для нескольких таблиц с несколькими столбцами.
Я ищу набор результатов примерно так:
+--------+---------+------------+-------------+-------------+----------------+
| person | beardID | beardStyle | beardLength | moustacheID | moustacheStyle |
+--------+---------+------------+-------------+-------------+----------------+
| bob | 1 | rasputin | 1 | | |
+--------+---------+------------+-------------+-------------+----------------+
| bob | 2 | samson | 12 | | |
+--------+---------+------------+-------------+-------------+----------------+
| bob | | | | 1 | fu manchu |
+--------+---------+------------+-------------+-------------+----------------+
есть ли способ достичь этого быстро и ремонтопригодно? Или мне лучше запустить отдельный запрос для каждого стол?
пояснение:
Я не ищу декартово произведение. Я не хочу ссориться из-за каждой комбинации бороды и усов, я хочу ссориться из-за каждой бороды и ссориться из-за каждого уса.
поэтому, если есть 3 одинаковых бороды и 2 одинаковых уса, я должен получить 5 строк, а не 6.
5 ответов
это должно работать нормально:
SELECT * FROM `beards` b LEFT OUTER JOIN `mustaches` ON (0) WHERE person = "bob"
UNION ALL
SELECT * FROM `beards` b RIGHT OUTER JOIN `mustaches` ON (0) WHERE person = "bob"
вам не нужно обрабатывать столбцы самостоятельно. левый и правый внешние соединения делают эту работу. к сожалению, mysql не имеет полного соединения. вот почему вы должны сделать это таким образом с Союзом
SELECT * FROM `customer` b LEFT OUTER JOIN `charges` ON (0) LEFT OUTER JOIN `day` ON (0)
UNION
SELECT * FROM `customer` b RIGHT OUTER JOIN `charges` ON (0) LEFT OUTER JOIN `day` ON (0)
UNION
SELECT * FROM `customer` b LEFT OUTER JOIN `charges` ON (0) RIGHT OUTER JOIN `day` ON (0)
это локальный тест, который я сделал
присоединиться к человеку....
т. е.
выберите Т1.(asterix), t2.(звездочка) ОТ бороды Т1 ВНУТРЕННЕЕ СОЕДИНЕНИЕ усы Т2 на Т2.person = t1.персона
мне было весело с этим, не уверен, что это полностью управляемо с тем, что еще вам нужно добавить, но он достиг цели.
create table beard (
person varchar(20)
,beardID int
,beardStyle varchar(20)
,beardLength int )
create table moustache(
person varchar(20)
,moustacheID int
,moustacheStyle varchar(20))
insert into beard
select 'bob', 1, 'rasputin', 1
union select 'bob', 2, 'samson', 12
insert into moustache
select 'bob', 1, 'fu manchu'
declare @facialhair table (
person varchar(20)
,beardID int
,beardStyle varchar(20)
,beardLength int
,moustacheID int
,moustacheStyle varchar(20))
declare @i int
declare @name varchar(20)
set @name = 'bob'
set @i = (select COUNT(*) from beard where person = @name)
+ (select COUNT(*) from moustache where person = @name)
print @i
while @i > 0
begin
insert into @facialhair (person, beardID, beardStyle, beardLength)
select person, beardID, beardStyle, beardLength
from beard
where person = @name
set @i = @i-@@ROWCOUNT
insert into @facialhair (person, moustacheID, moustacheStyle)
select person, moustacheID, moustacheStyle
from moustache
where person = @name
set @i = @i-@@ROWCOUNT
end
select *
from @facialhair
Я думаю, вам было бы лучше сделать запросы для данных в каждой таблице.
одна из других возможностей - объединить данные из всех столбцов в одну большую строку (вы можете выбрать какой-то знак для разделения значений столбца), тогда вы сможете использовать предложение union all для объединения результатов из каждого запроса-но тогда вам придется анализировать каждую строку.. И типы данных будут потеряны.