Как написать исполняемый файл postgreSQL для расчета среднего и процентного значения с использованием этой схемы?

Я изучаю SQL (самоучка). Я пытаюсь написать исполняемый SQL-запрос postgres, чтобы ответить на этот вопрос: на основе города происхождения (имя) рассчитайте процент поездок, в которых оплата был как минимум на 10% выше, чем в среднем для поездок из этого города.

Контекст: 1) Завершенная поездка определяется как поездка со статусом «завершена» в таблице аренды. 2) Только с учетом поездок за последние 30 дней.

С чего я начал (надеюсь, это выглядит хорошо):

SELECT n.name, r.origin_id, SUM(r.fare_dollars), AVG(r.fare_dollars), count(r.id)
FROM rentals r, neighborhood n
LEFT JOIN r ON r.origin_id = n.id
GROUP BY n.name;

На правильном пути?!

В чем мне нужна ваша помощь (если я прав в отношении этого подхода):

Вопрос потребует, чтобы я выполнил подзапрос, который извлечет все записи, чтобы увидеть, как они соотносятся со средней стоимостью проезда. Затем мне нужно будет написать еще один запрос, который скажет мне, какие из этих поездок стоили на 10% дороже, чем средняя стоимость проезда.

Я с нетерпением жду возможности увидеть любые идеи, которые вы можете предоставить! Дайте мне знать, если я могу предоставить любую дополнительную информацию.

Спасибо.

ваш вопрос не ясен. Во-первых, я мог бы сказать, что вы запутались с форматом соединения, разделенным запятыми, и форматом соединения ansi-92, и следует предпочесть второй стиль форматирования (ansi-92).

Barbaros Özhan 06.04.2019 22:46
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
1
66
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы думаете в правильном направлении, хотя ваши навыки запросов еще не развиты, верно? Я постараюсь объяснить, насколько это возможно, надеюсь, вы будете следовать (а если вы не можете, не стесняйтесь спрашивать).

Итак, во-первых, вам нужно знать, какова средняя стоимость проезда по каждому пункту отправления:

SELECT n.id, n.name, AVG(r.fare_dollars) AS average_fare
  FROM neighborhood n
  JOIN rentals r
    ON r.origin_id = n.id
 GROUP BY n.id, n.name

Это довольно простой запрос, хотя обычно вам здесь не нужен идентификатор. Однако мы собираемся использовать этот запрос для сравнения с отдельными поездками, поэтому мы просто присоединим его к нашей таблице аренды:

SELECT avg_per_neighborhood.name 
     , SUM(CASE 
            WHEN r.fare_dollars >= avg_per_neighborhood.average_fare * 1.1 THEN 1.0 
            ELSE 0 
          END) / COUNT(*) AS percAbove110
  FROM rentals r
  JOIN (SELECT n.id, n.name, AVG(r.fare_dollars) AS average_fare
          FROM neighborhood n
          JOIN rentals r
            ON r.origin_id = n.id
         GROUP BY n.id, n.name) avg_per_neighborhood
    ON r.origin_id = avg_per_neighborhood.id
 GROUP BY avg_per_neighborhood.name

Интересная часть, конечно, процент выше 10% выше, чем в среднем; поэтому сначала мы определяем, выше ли индивидуальная арендная плата объединенного среднего * 1,1 (или 110% от среднего), и является ли она доходом 1 или доходностью 0, если нет — это утверждение CASE. Мы суммируем их по районам (SUM(CASE ... END)) и делим на общее количество поездок в этом районе (COUNT(*)), что дает нам процент.

Этот запрос можно немного переписать, используя оконные функции:

SELECT subq.NAME
     , SUM(subq.isHigherThan110avg) / COUNT(*) AS percAbove110
  FROM (SELECT n.NAME
             , CASE 
                 WHEN r.fare_dollars > 1.1 * AVG(r.fare_dollars) OVER (PARTITION BY n.id) THEN 1.0 
                 ELSE 0 
               END AS isHigherThan110avg
          FROM neighborhood n
          JOIN rentals r
            ON r.origin_id = n.id
     ) subq
 GROUP BY subq.name

Здесь подзапрос subq сравнивает со средним встроенным значением, используя оконную функцию AVG(...) OVER (...), а внешний запрос просто агрегирует результаты.

Рабочий пример на dbfiddle

Вам, конечно, нужно применить свои собственные фильтры, например, завершенные и последние 30 дней, но суть вы уловили, надеюсь.

Большое спасибо за ваше объяснение. Это тщательно и так полезно. Очень признателен! И да, я еще не совсем готов с моими навыками запросов, но скоро буду. Спасибо еще раз!

Rozzebudd 08.04.2019 23:33

Совершенно никаких проблем. Если возможно, подумайте о том, чтобы проголосовать за мой ответ, чтобы пользователи, которые найдут этот вопрос в будущем, знали, что он правильный и помог.

MarcinJ 08.04.2019 23:36

Конечно! У меня есть еще один вопрос, так как я не уверен, что сделал это правильно. Как бы вы добавили фильтры, т. е. завершенные и последние 30 дней, в этот sql?

Rozzebudd 08.04.2019 23:49

Просто добавьте их после объединения, WHERE r.status = 'Completed' AND r.date_completed > current_date - interval '30 days' или что-то в этом роде (я не знаю названия ваших столбцов).

MarcinJ 08.04.2019 23:51

Спасибо! Я не был полностью в этой части, и это здорово. Я принял ваш ответ и сделал так, как вы просили, и получил следующее: Голоса, отданные теми, у кого репутация менее 15, записываются, но не изменяют общедоступную оценку публикации. В любом случае, я принял это, и это работает для всех, кто читает это! Большое спасибо, еще раз. У меня, безусловно, будет больше вопросов, поскольку я пытаюсь улучшить свои навыки запросов.

Rozzebudd 09.04.2019 00:07

Ах да, вы не можете проголосовать, потому что вы новичок, извините! Удачи и удачи, не стесняйтесь спрашивать, если вы застряли, и помните, что лучший способ научиться — это попробовать.

MarcinJ 09.04.2019 00:10

Другие вопросы по теме