【问题标题】:mySQL JOIN of several tables几个表的mySQL JOIN
【发布时间】:2017-10-20 11:59:39
【问题描述】:

我在 MySQL-DB (InnoDB) 中有以下三个表

UserTab
ID | Name  | ---
------------------
 1 | Tom   |
 2 | Dick  |
 3 | Harry |

EventTab
ID | Name      | ---
------------------
 1 | Easter    |
 2 | Holidays  |
 3 | ThxGiving |
 4 | Christmas |

ParticipationTab
ID | UserID | EventID
---------------------
 1 | 1      | 1
 2 | 1      | 2
 3 | 1      | 3
 4 | 2      | 1
 5 | 2      | 4
 6 | 3      | 3  

我想用我的查询实现以下结果:

QueryResultTab
UserTab.Name | EventTab.Name | NoPart | Names
-----------------------------------------------
 Tom         | Easter        | 2      | Tom, Dick
 Tom         | Holidays      | 1      | Tom
 Tom         | ThxGiving     | 2      | Tom, Harry
 Dick        | Easter        | 2      | Tom, Dick 
 Dick        | Christmas     | 1      | Dick
 Harry       | ThxGiving     | 2      | Tom, Harry

我确实知道 Count() 结合 GROUP 来获取参与者的数量
我知道 group-concat 来获取“名称”。

SELECT Event, GROUP_CONCAT(Name ORDER BY Name ASC SEPARATOR ', ') as Names  
FROM  
(SELECT ID as UserID, Name FROM X_Users WHERE ConditionA) AS UserTab  
INNER JOIN  
(SELECT EventID, UserID FROM X_Participation WHERE ConditionB) AS ParticipationTab  
ON UserTab.UserID = ParticipationTab.UserID  
INNER JOIN  
(SELECT ID as EventID, Event FROM X_Events WHERE ConditionC) AS EventTab  
ON ParticipationTab.EventID = EventTab.EventID  
GROUP BY EventTab.EventID

这给了我:

ConcatTab
EventTab.Name | Names  
---------------------------  
Easter        | Tom, Dick  
Holidays      | Tom  
ThxGiving     | Tom, Harry  
Easter        | Tom, Dick  
Christmas     | Dick  
ThxGiving     | Tom, Harry  

如您所见,我知道 JOIN。或许我也可以为此使用 LEFT 或 RIGHT JOIN。

对于其他部分,我使用此查询:

SELECT Name, Event, NoPart   
FROM (SELECT ID as UserID, Name FROM X_Users WHERE ConditionA) AS UserTab    
INNER JOIN (SELECT EventID, UserID FROM X_Participation WHERE ConditionB) AS PartTab   
ON UserTab.UserID = PartTab.UserID  
INNER JOIN (SELECT ID as EventID, Event FROM X_Events WHERE ConditionC) AS EvTab  
ON PartTab.EventID = EvTab.EventID  
INNER JOIN (SELECT EventID as CntID, COUNT(*) AS NoPart FROM X_Participation WHERE ConditionB) AS CntTab    
ON EvTab.EventID = CntTab.CntID  
ORDER BY UserTab.UserID

这给了我:

CountTab
UserTab.Name | EventTab.Name | NoPart 
--------------------------------------
 Tom         | Easter        | 2      
 Tom         | Holidays      | 1      
 Tom         | ThxGiving     | 2      
 Dick        | Easter        | 2      
 Dick        | Christmas     | 1      
 Harry       | ThxGiving     | 2      

但是如何将 ConcatTab 和 CountTab 合并/合并到 QueryResultTab 中?我想用 mysql_fetch_assco() 逐行检索 PHP 中的结果表。 请不要告诉我PDO之类的事情,我知道的。

另一种选择——我尽量避免——是在 PHP 循环中执行,并使用大量微小的 SQL 查询来实现结果。

【问题讨论】:

    标签: mysql sql inner-join group-concat


    【解决方案1】:

    根据您的示例数据,您希望参与表中的所有行都包含来自维度的信息。然后,您需要该表的摘要。

    这是一种在FROM 子句中使用子查询的方法:

    SELECT u.name, e.name, p2.numPart, p2.Names
    FROM X_Participation p INNER JOIN  
         X_Users u 
         ON u.UserID = p.UserID INNER JOIN  
         X_Events e
         ON p.EventID = e.EventID INNER JOIN
         (SELECT p2.EventId, COUNT(*) as numPart,
                 GROUP_CONCAT(u2.name SEPARATOR ', ') as names
          FROM X_Participation p2 INNER JOIN  
               X_Users u2 
               ON u2.UserID = p2.UserID
          GROUP BY p2.EventId
         ) p2
         ON p2.EventId = p.EventId;
    

    注意事项:

    • 如果您要使用表别名(应该这样做),请将它们缩短,不要比表名长。
    • 不要不必要地使用子查询。在实现子查询的 MySQL 中尤其如此。
    • 您可以在外部查询的WHERE 子句中添加其他条件。

    【讨论】:

    • 附带问题:在运行此查询之前创建一个临时表来替换子查询会提高性能,还是 MySQL 会自动处理?
    • @法老王。 . .如果性能是一个问题,可能还有其他方法可以让它发挥作用。创建一个临时表——尤其是使用正确的索引——可能会快一点。我认为不值得付出额外的努力。
    • @Gordon,感谢您提供快速有效的答案。长别名只是为了演示。
    • @togath 如果它帮助您解决了问题,请接受答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-29
    • 1970-01-01
    • 1970-01-01
    • 2015-02-27
    • 1970-01-01
    • 2013-04-19
    • 1970-01-01
    相关资源
    最近更新 更多