2012-04-10 4 views
2

Cette requête produit la bonne réponse:Combiner ces deux requêtes 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 

sortie:

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

Ceci est le résultat souhaité:

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

Ceci est une jointure que je peux utiliser, ce qui semble permettre à group_concat de corriger la jointure "admin, staff, other" - mais je ne sais pas comment l'incorporer dans la requête principale ci-dessus?

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 

La table users_roles:

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

Le tableau des rôles:

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

Répondre

2

Vous pouvez essayer:

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

Salut Marco - ça ne marche pas? "Colonne inconnue 'user_roles.role_ID' dans 'on clause'"? La réponse ci-dessus "fonctionne", mais elle est vraiment lente pour une raison ou une autre - j'essaie de faire fonctionner la vôtre ... – Laurence

+1

@Laurencei Changez-le en users_roles.role_id. –

+0

OUI !!!!!!!!!!!!!!!!!! Merci à vous deux!!!!!!!!!!!!!!!!!!!!!!!! + rep si je pouvais !!!!!!!!!!!!! M'a sauvé tellement de maux de tête! – Laurence

1

Peut-être quelque chose comme ceci:

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

je reçois une erreur « users_roles.short_name » est une colonne inconnue. J'ai édité ma question originale avec la table users_roles et la table de rôles pour clarifier. D'une manière ou d'une autre, j'ai besoin de rejoindre ces deux tables AVANT que le CONCAT se produise ...? – Laurence

2

Ajouter une table dérivée et rejoindre de nouveau aux utilisateurs. La table dérivée est utilisée en raison de la fonction d'agrégation sur overtime_list afin que les données ne soient pas dupliquées.

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

Je pense qu'il vous manque la table des rôles dans la clause from de la sous-sélection. – newenglander

+0

@newenglander Comme c'est vrai! Merci, j'ai corrigé ma réponse. –

+0

Pas de problème. J'aime cette requête car elle empêche la liste de sélection d'être trop longue. – newenglander

0

Je n'aime utiliser les fonctions utilisateur sur les requêtes en tant que moteur de base de données traite fonctions et ne peux pas optimiser boîtes noires requêtes à l'intérieur, afin de les éviter que possible. Avec croix vous appliquez vous obtiendrez le même résultat que intendend: (ne pas tester toutes les requêtes que je n'avez pas tous les objets utilisés)

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 est une fonction d'agrégat intégrée dans MySql. –

Questions connexes