MySQL PDO - последняя строка для таблицы, сгруппированной с объединениями - PullRequest
0 голосов
/ 16 января 2019

Я прошу прощения за описание заголовка, поскольку я не был уверен, как лучше всего описать это.

Существует несколько компьютеров, несколько пользователей на компьютер и несколько журналов данных на пользователя. Я хочу получить последний журнал данных для каждого компьютера.

Теперь я понимаю, что приведенный ниже запрос не предоставляет правильных данных, потому что для результатов происходит ORDER BY, а GROUP BY - в произвольном порядке.

Я прочитал об этом, прежде чем опубликовать это, и кажется, что нужен подзапрос, а затем результат этого снова соединяется с той же таблицей, чтобы получить оставшиеся значения столбца этих строк (найденный последним) , Приведенные мною примеры довольно просты и не предполагают объединения других таблиц. Мне также кажется, что мне нужно сделать это дважды, так как я хочу, чтобы это сгруппировалось по компьютеру ... (один раз для data_logs, сгруппированных по user_id и получить максимум, затем другой, сгруппированный по computer_id, чтобы получить максимум предыдущего результата), или, возможно, я ошибаюсь .

Нужна помощь, чтобы понять, как решить эту проблему, и как это сделать.

<code>$stmt = $db->prepare("
    SELECT
        computers.computer_name,
        users.username,
        data_logs.window_title,
        data_logs.filename,
        data_logs.capture_timestamp
    FROM computers
    INNER JOIN users
        ON users.computer_id = computers.computer_id
    INNER JOIN data_logs
        ON data_logs.user_id = users.user_id AND data_logs.marked != 1
    WHERE computers.account_id = :cw_account_id AND computers.status = 1
    GROUP BY computers.computer_id
    ORDER BY data_logs.capture_timestamp desc
");

$binding = array('cw_account_id' => 1721);
$stmt->execute($binding);
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);

echo "<pre>";
print_r($results);
echo "
";

1 Ответ

0 голосов
/ 16 января 2019

Одним из решений является использование коррелированного подзапроса. Принцип заключается в том, что внешний запрос не агрегируется, но имеет условие в предложении WHERE, которое выбирает самую последнюю запись журнала для текущего идентификатора компьютера, используя агрегированный подзапрос.

Полагаю, вам понадобится этот запрос (без просмотра данных примера и ожидаемого результата, хотя он может быть не точным на 100%):

SELECT
    computers.computer_name,
    users.username,
    data_logs.window_title,
    data_logs.filename,
    data_logs.capture_timestamp
FROM computers
INNER JOIN users
    ON users.computer_id = computers.computer_id
INNER JOIN data_logs
    ON data_logs.user_id = users.user_id AND data_logs.marked != 1
WHERE 
    computers.account_id = :cw_account_id 
    AND computers.status = 1
    AND data_logs.capture_timestamp = (
        SELECT MAX(d.capture_timestamp)
        FROM computers c
                INNER JOIN users u ON u.computer_id = c.computer_id
        INNER JOIN data_logs d ON d.user_id = u.user_id AND d.marked != 1
        WHERE c.computer_id = computers.computer_id AND c.account_id = computers.account_id
    )
ORDER BY data_logs.capture_timestamp desc
...