2012-04-10 94 views
2

此查询产生正确的答案:结合这两个MySQL查询

SELECT users.*, 
     SUM(overtime_list.shift_length) AS overtime_total, 
     (SELECT GROUP_CONCAT(users_roles.role_ID) FROM users_roles WHERE users.user_ID = users_roles.user_ID) AS roles 
    FROM availability_list 
    INNER JOIN users 
     ON users.user_ID = availability_list.user_ID 
    INNER JOIN stations 
     ON users.station_ID = stations.station_ID 
    INNER JOIN overtime_list 
     ON overtime_list.user_ID = users.user_ID 
     AND overtime_list.date >= '$totalovertimedays' 
    WHERE availability_list.date = '$date' 
    AND availability_list.type = '$type' 
    GROUP BY users.user_ID 
    ORDER BY overtime_total ASC 

输出:

+----------+---------+----------------------------+------------------+ 
| user_ID | user | roles     | overtime_total | 
+----------+---------+----------------------------+------------------+ 
|  1 | Smith | 1,2      |  12  | 
+----------+---------+----------------------------+------------------+ 
|  2 | Jones | 1,2,3     |  7   | 
+----------+---------+----------------------------+------------------+ 

这是所期望的结果:

+----------+---------+----------------------------+------------------+ 
| user_ID | user | roles     | overtime_total | 
+----------+---------+----------------------------+------------------+ 
|  1 | Smith | Admin, Staff   |  12  | 
+----------+---------+----------------------------+------------------+ 
|  2 | Jones | Admin, Staff, Other  |  7   | 
+----------+---------+----------------------------+------------------+ 

这是我可以使用的连接,它似乎允许group_concat更正连接“admin,staff,other” - 但我无法解决如何将它合并到上面的主查询中?

SELECT users.user_id, GROUP_CONCAT(roles.short_name separator ', ') roles 
FROM users 
JOIN users_roles ON users.user_ID = users_roles.user_ID 
JOIN roles ON users_roles.role_ID= users_roles.role_ID 
GROUP BY users.user_ID 

的users_roles表:

+----------+---------+ 
| user_ID | role_ID | 
+----------+---------+ 
|  1 | 1  | 
+----------+---------+ 
|  2 | 1  | 
+----------+---------+ 
|  2 | 2  | 
+----------+---------+ 
|  2 | 3  | 
+----------+---------+ 
|  1 | 3  | 
+----------+---------+ 

角色表:

+----------+------------+ 
| role_ID | short_name | 
+----------+------------+ 
|  1 | Admin | 
+----------+------------+ 
|  2 | Super | 
+----------+------------+ 
|  3 | Other | 
+----------+------------+ 

回答

2

你可以尝试:

SELECT users.*, 
     SUM(overtime_list.shift_length) AS overtime_total, 
     (SELECT GROUP_CONCAT(roles.short_name) FROM users_roles 
     INNER JOIN roles ON user_roles.role_ID = roles.role_ID 
     WHERE users.user_ID = users_roles.user_ID) AS roles 
    FROM availability_list 
    INNER JOIN users 
     ON users.user_ID = availability_list.user_ID 
    INNER JOIN stations 
     ON users.station_ID = stations.station_ID 
    INNER JOIN overtime_list 
     ON overtime_list.user_ID = users.user_ID 
     AND overtime_list.date >= '$totalovertimedays' 
    WHERE availability_list.date = '$date' 
    AND availability_list.type = '$type' 
    GROUP BY users.user_ID 
    ORDER BY overtime_total ASC 
+0

嗨马可 - 它不工作? “on子句'”中的未知列'user_roles.role_ID'?上面的答案“确实有效”,但由于某种原因,这确实很慢 - 我试图让你的工作... – Laurence 2012-04-10 11:02:47

+1

@Laurencei将其更改为users_roles.role_id。 – 2012-04-10 11:32:06

+0

是的!!!!!!!!!!!!!!!!!!谢谢你们俩!!!!!!!!!!!!!!!!!!!!!!!! +代表如果我能!!!!!!!!!!!!!让我非常头痛! – Laurence 2012-04-10 11:51:52

1

也许是这样的:

SELECT users.*, 
     SUM(overtime_list.shift_length) AS overtime_total, 
     (SELECT GROUP_CONCAT(users_roles.short_name) FROM users_roles WHERE users.user_ID = users_roles.user_ID) AS roles 
    FROM availability_list 
    INNER JOIN users 
     ON users.user_ID = availability_list.user_ID 
    INNER JOIN stations 
     ON users.station_ID = stations.station_ID 
    INNER JOIN overtime_list 
     ON overtime_list.user_ID = users.user_ID 
     AND overtime_list.date >= '$totalovertimedays' 
    WHERE availability_list.date = '$date' 
    AND availability_list.type = '$type' 
    GROUP BY users.user_ID 
    ORDER BY overtime_total ASC 
+0

我得到一个错误“users_roles.short_name”是一个未知的列。我已经用users_roles表和角色表修改了我的原始问题以阐明。不知何故,我需要在CONCAT发生之前加入这两张桌子......? – Laurence 2012-04-10 08:37:54

2

添加派生表,并加入回给用户。使用派生表是因为overtime_list上的聚合函数,因此数据不会重复。

SELECT users.*, 
    SUM(overtime_list.shift_length) AS overtime_total, 
    roles.roles 
FROM availability_list 
INNER JOIN users 
    ON users.user_ID = availability_list.user_ID 
INNER JOIN stations 
    ON users.station_ID = stations.station_ID 
INNER JOIN overtime_list 
    ON overtime_list.user_ID = users.user_ID 
    AND overtime_list.date >= '$totalovertimedays' 
LEFT JOIN 
(
    SELECT users_roles.user_ID, 
      GROUP_CONCAT(roles.short_name separator ', ') roles 
    from users_roles 
     INNER JOIN roles ON users_roles.role_ID = roles.role_ID 
    group by users_roles.user_ID 
) roles 
    ON users.user_ID = roles.user_ID 
WHERE availability_list.date = '$date' 
AND availability_list.type = '$type' 
GROUP BY users.user_ID 
ORDER BY overtime_total ASC 
+0

我想你错过了subselect的from子句中的roles表。 – newenglander 2012-04-10 08:22:05

+0

@newenglander如何真实!谢谢,我纠正了我的答案。 – 2012-04-10 08:26:02

+0

没问题。我喜欢这个查询,因为它可以防止选择列表变得太长。 – newenglander 2012-04-10 08:30:24

0

我从来不喜欢使用的查询功能,用户数据库引擎将作为黑盒和着内部优化查询,这样就可以避免它们成为可能。随着跨应用你会得到相同的结果intendend:(没有测试所有查询作为我没有使用的所有对象)

SELECT users.*, 
     SUM(overtime_list.shift_length) AS overtime_total, 
     LEFT(ISNULL(roles.roles, ', '), LEN(ISNULL(roles.roles, ', ')) - 1) as roles 
    FROM availability_list 
    INNER JOIN users 
     ON users.user_ID = availability_list.user_ID 
    CROSS APPLY (
     SELECT short_name + ', ' 
     FROM roles 
     inner users_roles ON roles.role_id = users_roles.role_ID 
     WHERE users.user_ID = users_roles.user_ID 
     ORDER BY roles.role_id 
     FOR XML PATH('') 
    ) roles (roles)   
    INNER JOIN stations 
     ON users.station_ID = stations.station_ID 
    INNER JOIN overtime_list 
     ON overtime_list.user_ID = users.user_ID 
     AND overtime_list.date >= '$totalovertimedays' 
    WHERE availability_list.date = '$date' 
    AND availability_list.type = '$type' 
    GROUP BY users.user_ID 
    ORDER BY overtime_total ASC 
+0

GROUP_CONCAT是MySql中的内置聚合函数。 – 2012-04-10 10:35:50