2015-01-13 2 views
0

У меня есть данные в реальном времени с парковочных счетчиков и вы хотите сравнить текущее состояние парковки с историческими данными. Мои данные содержат парковочные билеты с datetime_start, когда они покупаются, и datetime_stop, когда они больше не полезны.Сравнивать транзакции счетчика с историческими данными

Настоящий SQL работает, но ОЧЕНЬ медленный. Я предполагаю, что я каким-то образом пройти через все данные в несколько раз или некоторые другие вещи могут быть оптимизированы:

(SELECT "parking_meter_id", SUM(CASE WHEN Now() BETWEEN "datetime_start" AND "datetime_stop" THEN 1 ELSE 0 END) < ( 
SUM(CASE WHEN Now() - interval '1 week' BETWEEN "datetime_start" AND "datetime_stop" THEN 1 ELSE 0 END) + 
SUM(CASE WHEN Now() - interval '2 week' BETWEEN "datetime_start" AND "datetime_stop" THEN 1 ELSE 0 END) + 
SUM(CASE WHEN Now() - interval '3 week' BETWEEN "datetime_start" AND "datetime_stop" THEN 1 ELSE 0 END) + 
SUM(CASE WHEN Now() - interval '4 week' BETWEEN "datetime_start" AND "datetime_stop" THEN 1 ELSE 0 END) + 
SUM(CASE WHEN Now() - interval '5 week' BETWEEN "datetime_start" AND "datetime_stop" THEN 1 ELSE 0 END) + 
SUM(CASE WHEN Now() - interval '6 week' BETWEEN "datetime_start" AND "datetime_stop" THEN 1 ELSE 0 END) + 
SUM(CASE WHEN Now() - interval '7 week' BETWEEN "datetime_start" AND "datetime_stop" THEN 1 ELSE 0 END) + 
SUM(CASE WHEN Now() - interval '8 week' BETWEEN "datetime_start" AND "datetime_stop" THEN 1 ELSE 0 END) 
/8) AS available 
FROM "parking_meter_transactions" 
WHERE 
Now() BETWEEN "datetime_start" AND "datetime_stop" OR 
Now() - interval '1 week' BETWEEN "datetime_start" AND "datetime_stop" OR 
Now() - interval '2 week' BETWEEN "datetime_start" AND "datetime_stop" OR 
Now() - interval '3 week' BETWEEN "datetime_start" AND "datetime_stop" OR 
Now() - interval '4 week' BETWEEN "datetime_start" AND "datetime_stop" OR 
Now() - interval '5 week' BETWEEN "datetime_start" AND "datetime_stop" OR 
Now() - interval '6 week' BETWEEN "datetime_start" AND "datetime_stop" OR 
Now() - interval '7 week' BETWEEN "datetime_start" AND "datetime_stop" OR 
Now() - interval '8 week' BETWEEN "datetime_start" AND "datetime_stop" 
GROUP BY "parking_meter_id") AS transactions 

Основная идея заключается в том, чтобы подсчитать количество билетов, которые являются «законными», как сейчас(), и сравнить он с суммами за последние 8 недель в одно и то же время суток. Это может дать статистическое представление о том, должно ли быть место для парковки.

+0

Почему предложение WHERE охватывает 16 недель вместо 8? –

+0

У вас есть datetime_start и datetime_stop все в двойных кавычках (vs single). Возможно, было бы лучше показать образец ваших данных, отредактировав исходный вопрос ... и использовать пробелы или вкладки для удобства чтения. – DRapp

+0

@DRapp: Идентификаторы, такие как имена столбцов, принимают либо двойные кавычки, либо вообще не кавычки. Они не принимают одинарные кавычки. –

ответ

1

Я хотел бы предложить создать индекс покрытия для вашего запроса, основанного на

(datetime_start, datetime_stop, parking_meter_id) 

Таким образом, база данных не должны идти на сырье страниц данных для выполнения запроса.

Кроме того, отрегулируйте предложение WHERE, чтобы быть очень простым, как диапазон сравнения по дате. В вашем SUM (случай) блоки, да, вы должны различать между которыми неделю она применима, но ваш ИНЕКЕ может быть упрощен вниз к чему-то вроде

WHERE datetime_start > Now() - interval '2 months' 

Подумайте об этом ... ваш «NOW() «Звонок - это что бы то ни было ... Для усмешек просто предположим, что 13 января @ 12:00. Поскольку все ваш ИНЕК является «ИЛИ» вместе

Now - 2 months = Week of Nov 13 
Now - 2 months - 1 week = Week of Nov 20 
Now - 2 months - 2 weeks = Week of Nov 27 
... 
Now - 2 months - 8 weeks = Brings us back to Now... 

Так ваш период времени NET ничего, когда дата/время начала больше, чем 2 месяца назад.

Это говорит о том, что индекс, как предлагается, должен значительно повысить производительность. Посмотрите на сложность предложения WHERE, что он должен продолжать вычислять даты - соответствующие интервалы. Так как он не может эффективно использовать индекс, он, вероятно, захлебывается.

Наличие идентификатора счетчика в индексе поможет оптимизировать предложение GROUP BY.

ОБРАТНАЯ СВЯЗЬ за комментарий.

Все ваши даты завернуты в FARTHEST, теперь() - 2 месяца. Не рассматривайте что-либо до этого ... но теперь я вижу, что вы добавили дополнительные предложения WHERE, как только вы хотите получать билеты только для СПЕЦИФИЧЕСКОГО «СЕЙЧАС»() в течение недели в неделю в течение 8 недель. Таким образом, предложение where остается валиддом только при одном условии.

Позвольте двигателю пропустить все записи с этой даты/времени без сложных условий ГДЕ. Просто помните, что ваш COLUMN SELECTION через SUM (CASE/WHEN) будет рассчитываться только на основе «Legel» в течение рассматриваемого периода времени.

SUM (CASE WHEN Now() - интервал '1 неделя' МЕЖДУ "datetime_start" И "datetime_stop" THEN 1 ELSE 0 END) + SUM (CASE WHEN Now() - интервал '2 недели' МЕЖДУ "datetime_start" AND "datetime_stop" THEN 1 ELSE 0 END) +

Итак, если вы ищете что-то такое, как 2:53 днем, и у вас есть квалифицирующая запись WHERE, сделанная 2 января в datetime_start 7:59 pm, это приведет к сбою всех экземпляров CASE/WHEN, а NONE из столбцов результата будет добавлено к ним 1, игнорируя их.

Таким образом, даже если есть 10k записей за последние 2 месяца, пройдите через них быстро через индекс. Ваш случай/когда будет квалифицирован только для подсчета тех, которые относятся к периоду времени 2:53 (ex :), который вы ищете, и может рассчитывать только на 314 записей в течение всех недельных периодов. Такие, как

Wed, Jan 14 @ 2:53 
    Wed, Jan 7 @ 2:53 
    Wed, Dec 31 @ 2:53 
    Wed, Dec 24 @ 2:53 
    Wed, Dec 17 @ 2:53 
    Wed, Dec 10 @ 2:53 
    Wed, Dec 3 @ 2:53 
    Wed, Nov 26 @ 2:53 
    Wed, Nov 19 @ 2:53 
+0

Я попробую и отредактирую свою статью где завтра и вернусь с ответом. Причина моего первого выбора заключалась в том, чтобы выбрать только те, которые используются. При выборе ВСЕХ записей за последние 2 месяца я также получаю записи между желаемыми сравнениями. Имеют смысл? Но, возможно, это делает его более сложным и медленным, чем быстрее. – Henrik

+0

У меня уже есть указатель на (datetime_start, datetime_stop) и индекс на (parking_meter_id) – Henrik

+0

@Henrik, я понимаю ваш отдельный индекс, но наличие в качестве единственного препятствует необходимости использования механизма знания того, что использовать. Единица по датам И идентификатор парковочного счетчика может разрешить ПОЛНЫЙ запрос без перехода к исходным данным. – DRapp

Смежные вопросы