У меня есть 2 таблицы: пользователи (user_id, fname, lname, Department) и часы (id, punchType, punchTime, comment, user_id).

SQL-запрос ниже извлекает 2 строки для некоторых записей, и я не могу понять, почему. Любое понимание было бы полезно.

SELECT user.user_id, user.fname, user.lname, user.department, punchType, punchTime, comment
    FROM user
    INNER JOIN (
        SELECT *
        FROM clock
        WHERE punchTime IN (
         SELECT MAX(punchTime) 
         FROM clock
         GROUP BY user_id
        )
       ) AS a
       ON user.user_id = a.user_id
0
John Stempien 24 Сен 2018 в 19:39

2 ответа

Лучший ответ

Потому что у разных пользователей может быть одно и то же время punch. Время работы одного пользователя может быть максимальным временем работы другого пользователя. Вот одно исправление:

        SELECT *
        FROM clock
        WHERE (user_id, punchTime) IN (
                SELECT user_id, MAX(punchTime) 
                FROM clock
                GROUP BY user_id
               );

Это также можно исправить с помощью коррелированных подзапросов и других методов.

1
Gordon Linoff 24 Сен 2018 в 16:44

Вы заметите, что когда вы выполняете подзапрос только с помощью punchTime, вы можете получить дублирующиеся записи для каждого пользователя. Что происходит: если любое из значений punchTimes пользователя соответствует максимальному времени удара, они остаются в наборе. Итак, если у пользователя есть максимальное время, которое соответствует максимальному времени другого пользователя, или у пользователей есть две записи +, которые представляют их собственное максимальное время удара, вы будете объединять несколько строк одного и того же user_id из clock с таблицей пользователя.

Например:

SELECT
  user_id,
  MAX(punchTime) as real_max_time,
  COUNT(1) as dupe_count,
  COUNT(DISTINCT(punchTime)) as unique_punchTimes
  COUNT(DISTINCT(punchType)) as unique_punchTypes
FROM clock
WHERE punchTime IN (
    SELECT MAX(punchTime) 
    FROM clock
    GROUP BY user_id
)
GROUP BY 
  user_id
HAVING COUNT(1) > 1

В противном случае у вас может быть дублированный user_id в вашей таблице пользователей. Может быть, один пользователь работал в нескольких отделах? или поменяли имена?

Найдите повторяющиеся user_id со следующим:

SELECT
  user_id,
  COUNT(1) as duplicate_user_count
FROM user
GROUP BY user_id
HAVING COUNT(1) >1

Собираем все вместе - найдите, где происходит дублирование, а затем добавьте другие столбцы, которые вам небезразличны, когда они будут разрешены:

SELECT
    users.user_id,
    users.dupe_users,
    max_time.distinct_punchtimes,
    max_time.distinct_punchtypes,
    max_time.max_punchTime
FROM (
    SELECT
        user_id,
        COUNT(1) as dupe_users
    FROM user
    GROUP BY
      user_id 
) as users
INNER JOIN (
    SELECT
        user_id,
        COUNT(1) as clock_rows,
        COUNT(DISTINCT(punchTime)) as distinct_punchtimes,
        COUNT(DISTINCT(punchType)) as distinct_punchtypes,
        MAX(punchTime) max_punchTime
    FROM clock
    GROUP BY user_id
) as max_time
ON users.user_id = max_time.user_id
0
JLuxton 24 Сен 2018 в 18:28