Sokil.Dmytro
Новичок
выборка из двух таблиц и агрегатные функции
есть таблица с пользователями
CREATE TABLE USRLGN(
ID Integer NOT NULL, # ID пользователя
UGRP Integer NOT NULL, # группа, к которой принадлежит пользователь
LGN Char(10) NOT NULL,
...
);
есть таблица с данными о сессиях пользователя
CREATE TABLE SESINF(
U_ID Integer NOT NULL, # ссылается на USRLGN.ID
LGN_DT Timestamp NOT NULL, # время последнего входа
LST_DT Timestamp NOT NULL, # время последнего действия пользователя
...
);
При каждом логине сюда записываются (INSERT) данные сессии и время логина, при каждом запросе страници - обновляется поле LST_DT.
Тоесть отношение один USRLGN ко многим SESINF.
Задача: выбрать всех пользователей конкретной группы USRLGN.UGRP из таблици USRLGN и добавить туда дату последнего входа и последнего действия для конкретного пользователя
Задачу решил двумя способами:
Способ 1 . SELECT usrlgn.LGN, usrlgn.UGRP, sesinf.U_ID, MAX(sesinf.LGN_DT), MAX(sesinf.LST_DT)
FROM SESINF sesinf LEFT OUTER JOIN USRLGN usrlgn ON usrlgn.ID = sesinf.U_ID
GROUP BY sesinf.U_ID, usrlgn.LGN, usrlgn.UGRP
HAVING usrlgn.UGRP = 2
Результат: Полный звиздец, так как все поля надо перечислять в списке группировки
Способ 2. первый запрос сливает данные с USRLGN по всем юзерам для USRLGN.UGRP = 2
второй запрос:
SELECT sesinf.U_ID, MAX(sesinf.LST_DT) as LST_DT, MAX(sesinf.LGN_DT) as LGN_DT
FROM SESINF sesinf LEFT OUTER JOIN USRLGN usrlgn ON usrlgn.ID = sesinf.U_ID
WHERE usrlgn.UGRP = 2
GROUP BY sesinf.U_ID
получает максимальные значения для каждого пользователя из заданной группы usrlgn.UGRP. потом два массива сливаются уже на уровне PHP. В итоге выборка юзеров по группе происходит два раза.
Как вариант решения, можно получить все айдишники пользователей в первом запросе, и избавиться от JOIN'ов во втором, сделав поиск по айдишникам WHERE sesinf.U_ID IN(id,id,id,id)
Результат: Звиздец круче первого
Ктото подскажет более адекватное решение?
-~{}~ 27.09.09 02:26:
придумал еще одну двухєтажную хренотень:
SELECT
usrlgn.*, sesinf.LGN_DT, sesinf.LST_DT
FROM
USRLGN usrlgn
LEFT OUTER JOIN (
SELECT
U_ID, MAX(LGN_DT) as LGN_DT, MAX(LST_DT) as LST_DT
FROM SESINF
GROUP BY U_ID
) as sesinf
ON usrlgn.ID = sesinf.U_ID
WHERE usrlgn.UGRP = 2
как по мне, не самое адекватное и красивое решение, во первых все равно два запроса, а во вторых вложенный запрос вытянет всю таблицу а уже потом ее слинкует.
есть таблица с пользователями
CREATE TABLE USRLGN(
ID Integer NOT NULL, # ID пользователя
UGRP Integer NOT NULL, # группа, к которой принадлежит пользователь
LGN Char(10) NOT NULL,
...
);
есть таблица с данными о сессиях пользователя
CREATE TABLE SESINF(
U_ID Integer NOT NULL, # ссылается на USRLGN.ID
LGN_DT Timestamp NOT NULL, # время последнего входа
LST_DT Timestamp NOT NULL, # время последнего действия пользователя
...
);
При каждом логине сюда записываются (INSERT) данные сессии и время логина, при каждом запросе страници - обновляется поле LST_DT.
Тоесть отношение один USRLGN ко многим SESINF.
Задача: выбрать всех пользователей конкретной группы USRLGN.UGRP из таблици USRLGN и добавить туда дату последнего входа и последнего действия для конкретного пользователя
Задачу решил двумя способами:
Способ 1 . SELECT usrlgn.LGN, usrlgn.UGRP, sesinf.U_ID, MAX(sesinf.LGN_DT), MAX(sesinf.LST_DT)
FROM SESINF sesinf LEFT OUTER JOIN USRLGN usrlgn ON usrlgn.ID = sesinf.U_ID
GROUP BY sesinf.U_ID, usrlgn.LGN, usrlgn.UGRP
HAVING usrlgn.UGRP = 2
Результат: Полный звиздец, так как все поля надо перечислять в списке группировки
Способ 2. первый запрос сливает данные с USRLGN по всем юзерам для USRLGN.UGRP = 2
второй запрос:
SELECT sesinf.U_ID, MAX(sesinf.LST_DT) as LST_DT, MAX(sesinf.LGN_DT) as LGN_DT
FROM SESINF sesinf LEFT OUTER JOIN USRLGN usrlgn ON usrlgn.ID = sesinf.U_ID
WHERE usrlgn.UGRP = 2
GROUP BY sesinf.U_ID
получает максимальные значения для каждого пользователя из заданной группы usrlgn.UGRP. потом два массива сливаются уже на уровне PHP. В итоге выборка юзеров по группе происходит два раза.
Как вариант решения, можно получить все айдишники пользователей в первом запросе, и избавиться от JOIN'ов во втором, сделав поиск по айдишникам WHERE sesinf.U_ID IN(id,id,id,id)
Результат: Звиздец круче первого
Ктото подскажет более адекватное решение?
-~{}~ 27.09.09 02:26:
придумал еще одну двухєтажную хренотень:
SELECT
usrlgn.*, sesinf.LGN_DT, sesinf.LST_DT
FROM
USRLGN usrlgn
LEFT OUTER JOIN (
SELECT
U_ID, MAX(LGN_DT) as LGN_DT, MAX(LST_DT) as LST_DT
FROM SESINF
GROUP BY U_ID
) as sesinf
ON usrlgn.ID = sesinf.U_ID
WHERE usrlgn.UGRP = 2
как по мне, не самое адекватное и красивое решение, во первых все равно два запроса, а во вторых вложенный запрос вытянет всю таблицу а уже потом ее слинкует.