Как объединить результаты из нескольких таблиц с разными столбцами? - PullRequest
7 голосов
/ 26 октября 2010

У меня есть несколько таблиц с разными номерами и типами столбцов и одним общим столбцом.

+--------+---------+------------+-------------+
| person | beardID | beardStyle | beardLength |
+--------+---------+------------+-------------+

+--------+-------------+----------------+
| person | moustacheID | moustacheStyle |
+--------+-------------+----------------+

Я хочу получить все результаты, которые соответствуют заданному значению общего столбца.Я могу сделать это, используя несколько операторов выбора, таких как:

SELECT * FROM beards WHERE person = "bob"

и

SELECT * FROM moustaches WHERE person = "bob"

Но для этого требуется несколько вызовов API mysql, что кажется неэффективным.Я надеялся, что смогу использовать 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 ]

7 голосов
/ 27 октября 2010

это должно работать нормально:

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)

это локальный тест, который я сделал

0 голосов
/ 27 октября 2010

Я думаю, вам было бы лучше, если бы вы запрашивали данные в каждой таблице.

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

0 голосов
/ 26 октября 2010
SELECT *
FROM   beards
       JOIN moustaches
         ON moustaches.person = beards.person
WHERE  person = "bob"  
0 голосов
/ 27 октября 2010

Мне было весело с этим, не уверен, что это вполне поддается управлению тем, что еще нужно добавить, но это достигло цели.

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
0 голосов
/ 26 октября 2010

Присоединяйтесь к человеку ....

Т.е.

Выберите t1. (Звездочка), t2. (Звездочка) ОТ бороды t1 ВНУТРЕННИЕ ПРИСОЕДИНЯЕТСЯ Усы t2 На t2.person = t1.person

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...