2014-02-03 2 views
0

У меня есть таблица со следующей структурой в PostgresSQL автообъединение и агрегация

Таблицы пути: пассажиров, происхождение, точки назначения, дата, месяц, год

Я хочу, чтобы найти лучшие 3 марштутам по количеству пассажиров, путешествующих по маршруту в год. Общее количество пассажиров на маршруте (A < -> B) = общее количество пассажиров (A -> B) + общее количество пассажиров (B-> A)

Что является лучшим/оптимальным способом для объединения Количество пассажиров на маршруте, количество строк в таблице составляет около 150 миллионов строк.

Благодаря

ответ

0

Если каждый маршрут используется в обоих направлениях, которые должны дать вам ответ:

SELECT (x.passengers + y.passengers) as passenders_sum, x.origin, y.dest 
FROM yourTable x 
JOIN yourTable y 
ON x.origin = y.dest AND x.dest = y.origin 
ORDER BY passenders_sum DESC; 

С индексами по вашему происхождению и Dest столбцов, автообъединение не должно заставить вас беспокоиться. Я не вижу возможности избежать операции такого масштаба, чтобы получить запрошенный результат. Вам нужно будет добавить какой-то LIMIT в этот оператор, если вам нужны только первые X строк. У меня нет опыта postgres.

+0

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

+0

В защиту СебастьянаH я также предполагал, что каждая строка уникальна в каждом направлении. В конце концов, это не наши данные. Я обновил свой ответ, и этот вариант можно изменить так же. –

+0

@AchimSchmitz Спасибо;) И этот ответ точно так же, как я пойду без более глубокого понимания данных. – SebastianH

4

Существует два подхода к этому. Один из них - агрегация, а другие - объединения.

select least(origin, dest) as od1, greatest(origin, dest) as od2, sum(passengers) as numpassengers 
from path t 
group by least(origin, dest), greatest(origin, dest) 
order by numpassengers 
limit 3; 

Другое - это самостоятельное объединение. Если есть только одна строка в каждом направлении, вы можете сделать это без агрегации:

select p1.origin, p1.dest, p1.passengers + p2.passengers as numpassengers 
from path p1 join 
    path pt2 
    on p1.origin = p2.dest and p1.dest = p2.origin 
where p1.origin < p1.dest 
order by numpassengers desc 
limit 3; 

В противном случае, вам нужно самостоятельно присоединиться и агрегации, поэтому первый метод, вероятно, быстрее:

select p1.origin, p1.dest, sum(p1.passengers + p2.passengers) as numpassengers 
from path p1 join 
    path pt2 
    on p1.origin = p2.dest and p1.dest = p2.origin 
where p1.origin < p1.dest 
group by p1.origin, p1.dest 
order by numpassengers desc 
limit 3; 

I не знаю, что было бы более эффективным. Тем не менее, я подозреваю, что верхние 3 маршрута по сумме будут, скажем, 100 лучших для каждого направления. Если да, то построить индекс на numpassengers и попробовать:

select least(origin, dest) as od1, greatest(origin, dest) as od2, sum(passengers) as numpassengers 
from path t cross join 
    (select min(passengers) as cutoff 
     from (select distinct passengers 
      from path 
      order by passengers desc 
      limit 100 
      ) t 
    ) minp 
where numpassengers >= minp.cutoff 
group by least(origin, dest), greatest(origin, dest) 
order by numpassengers 
limit 3; 

Расчет обрезания должен просто использовать индекс и значительно снизить нагрузку на остальной части запроса.

EDIT:

Если у вас нет least() и greatest(), просто использовать case заявления:

select (case when origin < dest then origin else dest end) as od1, 
     (case when origin < dest then dest else origin end) as od2, 
     sum(passengers) as numpassengers 
from path t 
group by 1, 2 
order by numpassengers 
limit 3; 

Вы можете повторить case заявления в group by. Но Amazon Redshift позволяет ссылаться на псевдонимы или позиции столбцов в предложении group by.

+0

Работает метод агрегирования. Мне нужно выяснить, как он работает. - Спасибо. Второй запрос (метод самосоединения) не объединяется в колонку подсчета пассажиров, чтобы обеспечить уникальное происхождение, целевую пару с общим количеством пассажиров. Запрос приводит к дублированию маршрутов с агрегацией, не полностью применяемой в колонке подсчета пассажиров. -- Спасибо за ответ. –

+0

@SanthoshS. , , Я думаю, что я неправильно понял небольшую часть проблемы. Вероятно, наилучшим подходом является агрегация без объединения. –

+0

Я попробовал это в mysql, postgresql, и запрос работает отлично. Спасибо. Наименьшие и самые большие функции недоступны в Amazon Redshift - любые альтернативы, чтобы получить первый запрос на Amazon Redshift. Спасибо –

0

Я думаю, что SebastianH это правильно. В качестве небольшого улучшения вы можете попробовать следующее предполагая PostgresSQL поддерживает положение SELECT TOP:

SELECT TOP 3 
    FROM (SELECT (SUM(A.PASSENGERS + B.PASSENGERS), A.ORIGIN, A.DEST) 
      FROM YOURTABLE A JOIN YOURTABLE B 
      ON (A.ORIGIN = B.DEST AND A.DEST = B.ORIGIN) 
      GROUP BY A.ORIGIN, A.DEST 
     ) 
+0

да, выберите верхнюю часть можно использовать для ограничения результатов. –

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