SQL: головоломка «Группировка и подсчет» - PullRequest
0 голосов
/ 13 сентября 2018

Вот примерный список пользователей и станции / времени, когда они начинают свое транзитное путешествие, и станции / времени, когда они заканчивают:

user    Ststation   Starttime   endstation  endtime
bgh567  StationA    5:00:00     StationB    7:00:00
abc645  StationD    4:00:00     StationX    4:15:00
yh564   StationG    2:00:00     StationA    17:00:00
Yghf78  StationB    6:00:00     StationC    2:45:00

... этот список НАМНОГО длиннее и в течение дня.

Моя цель - подсчитать на каждую станцию ​​количество пользователей, которые начали и закончили свою поездку для каждой станции с 15-минутными интервалами.Таким образом, результат будет выглядеть так (подсчеты, которые я сделал, являются образцами и не представляют таблицы сэмплов в этом посте):

Time    Station     Enter   Exit
2:00:00 StationA    1      0
2:15:00 StationA    58     23
2:45:00 StationA    36     78
3:00:00 StationA    0      76

... и так далее до конца дня.А потом, когда Станция A будет закончена, StationB будет рассчитана и т. Д.

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

SELECT starttime, ststation, COUNT(user) as count_enter
  FROM sourcetable 
  GROUP BY starttime, ststation 
  ORDER BY ststation, starttime

И аналогичный дляколичество выходовНо я сталкиваюсь с проблемами, соединяющими их вместе, чтобы создать конечный результат выше.Я делаю это в Spark SQL, но если я понимаю методологию, я могу адаптировать любой ответ к моей среде.Есть мысли?

1 Ответ

0 голосов
/ 13 сентября 2018

Это запрос для Oracle.Измените функции, используемые в вашей соответствующей РСУБД:

WITH table_name AS 
(
    SELECT 'bgh567' AS user_name, 'StationA' AS station, sysdate + 1/(24*60) AS starttime, 'StationB' AS endstation, sysdate + 18/(24*60) AS endtime FROM dual UNION ALL
    SELECT 'abc645'AS user_name , 'StationD' AS station, sysdate + 15/(24*60) AS starttime, 'StationX' AS endstation, sysdate + 17/(24*60) AS endtime FROM dual UNION ALL
    SELECT 'yh564' AS user_name , 'StationG' AS station, sysdate + 12/(24*60) AS starttime, 'StationA' AS endstation, sysdate + 28/(24*60) AS endtime FROM dual UNION ALL
    SELECT 'Yghf78'AS user_name , 'StationB' AS station, sysdate + 13/(24*60) AS starttime, 'StationC' AS endstation, sysdate + 19/(24*60) AS endtime FROM dual 
)
, enter_table AS
(
    SELECT 
        TO_CHAR(starttime, 'yyyy/mm/dd') || ' ' || TO_CHAR(starttime, 'hh24') 
            || ':' || TO_CHAR(FLOOR(TO_CHAR(starttime, 'MI') / 15) * 15, 'FM00') 
            || ':00' AS time_interval,
        station,
        COUNT(*) AS enter
    FROM table_name
    GROUP BY TO_CHAR(starttime, 'yyyy/mm/dd'),
        TO_CHAR(starttime, 'hh24'),
        FLOOR(TO_CHAR(starttime, 'MI') / 15),
        station
)
, exit_table AS
(
    SELECT 
        TO_CHAR(endtime, 'yyyy/mm/dd') || ' ' || TO_CHAR(endtime, 'hh24') 
            || ':' || TO_CHAR(FLOOR(TO_CHAR(endtime, 'MI') / 15) * 15, 'FM00') 
            || ':00' AS time_interval,
        endstation AS station,
        COUNT(*) AS exit
    FROM table_name
    GROUP BY TO_CHAR(endtime, 'yyyy/mm/dd'),
        TO_CHAR(endtime, 'hh24'),
        FLOOR(TO_CHAR(endtime, 'MI') / 15),
        endstation
)

SELECT
    COALESCE(e.time_interval, ex.time_interval) AS time_interval, 
    COALESCE(e.station, ex.station) AS station,
    COALESCE(e.enter, 0) AS enter,
    COALESCE(ex.exit , 0) AS exit 
FROM enter_table e
FULL OUTER JOIN exit_table ex
ON e.time_interval = ex.time_interval
    AND e.station = ex.station
ORDER BY 1, 2;
...