Php 如何组合具有不同列的多个表的结果?
我有几个表,它们有不同的列数和类型,还有一个共同的列Php 如何组合具有不同列的多个表的结果?,php,mysql,join,union,Php,Mysql,Join,Union,我有几个表,它们有不同的列数和类型,还有一个共同的列 +--------+---------+------------+-------------+ | person | beardID | beardStyle | beardLength | +--------+---------+------------+-------------+ +--------+-------------+----------------+ | person | moustacheID | moustacheSt
+--------+---------+------------+-------------+
| person | beardID | beardStyle | beardLength |
+--------+---------+------------+-------------+
+--------+-------------+----------------+
| person | moustacheID | moustacheStyle |
+--------+-------------+----------------+
我想获取与共享列的给定值匹配的所有结果。我可以使用多个select语句来执行此操作,如下所示:
SELECT * FROM beards WHERE person = "bob"
+--------+---------+------------+-------------+-------------+----------------+
| person | beardID | beardStyle | beardLength | moustacheID | moustacheStyle |
+--------+---------+------------+-------------+-------------+----------------+
| bob | 1 | rasputin | 1 | | |
+--------+---------+------------+-------------+-------------+----------------+
| bob | 2 | samson | 12 | | |
+--------+---------+------------+-------------+-------------+----------------+
| bob | | | | 1 | fu manchu |
+--------+---------+------------+-------------+-------------+----------------+
及
但这需要多个mysql API调用,这似乎效率低下。我希望我可以使用UNIONALL在一个API调用中获得所有结果,但UNION要求表具有相同数量和相似类型的列。我可以编写一个SELECT语句,通过添加带有NULL值的列来手动填充每个表的结果,但是如果有更多的表包含更多的列,则很快就会变得无法管理
我正在寻找一个大致如下的结果集:
SELECT * FROM beards WHERE person = "bob"
+--------+---------+------------+-------------+-------------+----------------+
| person | beardID | beardStyle | beardLength | moustacheID | moustacheStyle |
+--------+---------+------------+-------------+-------------+----------------+
| bob | 1 | rasputin | 1 | | |
+--------+---------+------------+-------------+-------------+----------------+
| bob | 2 | samson | 12 | | |
+--------+---------+------------+-------------+-------------+----------------+
| bob | | | | 1 | fu manchu |
+--------+---------+------------+-------------+-------------+----------------+
有没有一种快速且可维护的方法来实现这一点?还是最好对每个表运行单独的查询
澄清:
我不是在寻找笛卡尔积。我不想让胡子和胡子的每一个组合都排成一行,我想让每个胡子排成一行,每个胡子排成一行
因此,如果有3个相配的胡须和2个相配的胡子,我应该得到5排,而不是6排。加入person
即
挑选
t1(星号),t2(星号)
从…起
胡须t1
内连接
t2上的胡须t2.person=t1.person我对此很感兴趣,不确定你还需要添加什么,但它实现了目标
SELECT *
FROM beards
JOIN moustaches
ON moustaches.person = beards.person
WHERE person = "bob"
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
这应该很好:
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)
这是我做的本地测试我认为查询每个表中的数据会更好
另一种可能性是将所有列中的数据连接成一个大字符串(您可以选择一些符号来分隔列的值),然后您应该能够使用union all子句来组合来自每个查询的结果,但随后您必须解析每一行。。数据类型将丢失。您尝试过这个吗?内部联接从两个表中检索匹配记录的笛卡尔积。因此,胡须和胡子的每一种组合都会产生一个结果。根本不是问题中所描述的。@Robert:不,内部联接不会产生笛卡尔积。对不起,我不太理解联接。内部联接与采用笛卡尔积并根据联接条件进行过滤有什么区别?内部联接选择关系A中的所有记录以及关系B中具有共同值的所有记录,并输出包含这些行的结果集。笛卡尔积是创建一个结果集的结果,其中关系a和B中的所有行都毫无韵律或理由地挂在一起。也就是说,对于关系A中的每一行,关系B中的每一行都被添加到结果集中。那么,内部联接不就是这样做的吗?对于关系A中的每一行,将关系B中的每一行添加到结果集中,然后过滤该集,以便仅返回具有公共值的行。如果有差异,我仍然看不到。我希望为每个胡子检索一行,为每个胡子检索一行,而不是为每个胡子检索一行。主要缺点是计算开销和mysql对组_concat的字符串大小有限!看看我的解决方案。我认为这是最简单的方法。@ITroubs:我应该说,这是一个很好的解决方案,非常棒,很有魅力。因此,如果我理解正确,您使用的是左外部联接和右外部联接,而没有指定联接条件,以向每个表的结果中添加满null的列(以便结果集具有匹配的表),然后联合results.yep。连接只是为了使舒尔的结果包含胡须和胡须的所有列,通过使ON语句为false,它只返回胡须或胡须的所有行,具体取决于使用的连接。若要添加第三个表,我将在新表的每个选择中添加一个额外的外部连接ON(0),加上UNION ALL和一个新的select语句,外部以相同的方式将新表连接到这两个表。刚才看到你说的正是我所说的XDi在我的解决方案中添加了一个三表示例,而这可以在大多数数据库中通过
完全连接来完成,在MySQL中通过ITroubs的解决方案来完成,我严重怀疑这是否会带来显著的性能提升,而且您可能只是在创建一堆您的继任者不会感谢您的晦涩代码。在大多数情况下,清晰和精确的代码在非常低的百分比下超过了性能增益。