2013-02-24 53 views
2

我重构了一些代码,并试图尝试提高可读性和性能。是否可以将多行的结果压缩到SQL查询中的一行上的设置对象中?

让我感到困惑的一件事是我需要一个连接语句的情况,一边有多个对象。例如...

Foo Schema   Bar 2 Schema 
--------------  --------------- 
id     id 
data    fooId 
        data 

Result from Search: 
--------------------- 
id barId fooData 
1 1  ... 
1 2  ... 
1 3  ... 
2 4  ... 
3 5  ... 

我的最终结果,查询对象的Foo时,必须包含ID(或物体中取出基于标识的),这些相关的对象美孚。

目前,我发现不得不压缩PHP级别的多行,将bar id添加到Foo,直到foo id更改。这有点难看,但确实有效。我想减少我的结果集是什么:

Result from Search: 
--------------------- 
id barIds fooData 
1 [1,2,3] ... 
2 4  ... 
3 5  ... 

有什么办法可以在SQL级别执行此操作吗? (注意,我不在寻找字符串1,2,3,我想要一个由id的1,2和3组成的数组 - 但是如果我必须接受一个字符串然后转换,我可以)

另外,我的意图是将它与PDO :: fetch_class结合起来,让我在一行中实例化类,而不用花费大量时间编写许多行代码来加载属性类。

回答

4

听起来就像你在使用GROUP_CONCAT。这将结合所有的酒吧ID。事情是这样的:

SELECT F.Id, GROUP_CONCAT(B.Id) BarIds, F.data 
FROM Foo F 
    INNER JOIN Bar B ON F.Id = B.FooId 
GROUP BY F.Id 

如果你想获得你的确切格式,请尝试使用CONCAT

CONCAT('[',GROUP_CONCAT(B.Id),']') BarIds 

这里有一个SQL Fiddle Demo

- 编辑 -

如果在默认情况下与GROUP_CONCAT存储的字符长度的关注(检查了这link出),另一种替代的方法是通过做模拟GROUP_CONCAT的行为这样的事情:

SELECT Id, BarIds, Data 
FROM (
    SELECT F.Id, 
     MAX(@barIdsCombined:=IF(@prevFoodId=F.Id, 
          CONCAT(@barIdsCombined,',',B.Id), 
         B.Id)) BarIds, 
     F.data, 
     @prevFoodId:=F.Id 
    FROM Foo F 
     INNER JOIN Bar B ON F.Id = B.FooId 
     JOIN (SELECT @barIdsCombined:='') t 
    GROUP BY F.Id 
) t 
+0

请小心使用'GROUP_CONCAT',因为它具有非常低的人为限制。你可以更新它('group_concat_max_len')。我已经走下了使用MySQL进行聚合的道路,包括'GROUP_CONCAT'。经验告诉我,使用查询语言进行聚合通常要好得多,因为MySQL的权限非常有限 – 2013-02-24 02:26:30

+0

我只使用[和]来表明它可能会以数组的形式访问PHP,而IIRC - PDO处理SQL集数据类型。 – RonLugge 2013-02-24 03:36:48

+0

@ExplosionPills通过'聚合查询语言',我假设你的意思是PHP?这真的是一个伟大的想法 - 看起来这对于SQL来说能够通过后台查询优化和缓存来减少开销来说是一个很好的地方。 – RonLugge 2013-02-24 03:37:50

相关问题