2

このクエリは正しい答えを生成します:

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    |
+----------+------------+
4

4 に答える 4

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
于 2012-04-10T08:12:39.943 に答える
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
于 2012-04-10T08:13:35.717 に答える
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
于 2012-04-10T08:12:36.167 に答える
0

データベースエンジンは関数をブラックボックスとして扱い、内部でクエリを最適化できないため、クエリでユーザー関数を使用することは決して好きではありません。可能な限り避けてください。クロス適用を使用すると、意図したものと同じ結果が得られます: (すべてのオブジェクトを使用していないため、すべてのクエリをテストしませんでした)

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 
于 2012-04-10T10:02:54.903 に答える