Как создавать группы и группы внутри этих групп, используя PostgresQL - PullRequest
0 голосов
/ 03 июля 2018

Как узнать распределение кредитных карт по годам и завершенных транзакций. Сгруппируйте эти кредитные карты в три группы: менее 10 транзакций, от 10 до 30 транзакций, более 30 транзакций?

Первый метод, который я пытался использовать, использовал функцию width_buckets в PostgresQL, но в документации говорится, что он создает только эквидистантные сегменты, что в данном случае не то, что я хочу. Из-за этого я обратился к материалам дела Однако я не уверен, как использовать оператор case с группой по.

Вот данные, с которыми я работаю:

table 1 - credit_cards table
credit_card_id
year_opened


table 2 - transactions table
transaction_id
credit_card_id - matches credit_cards.credit_card_id
transaction_status ("complete" or "incomplete")

Это то, что я получил до сих пор:

SELECT 

CASE WHEN transaction_count < 10 THEN “Less than 10”
WHEN transaction_count >= 10 and transaction_count < 30 THEN “10 <= transaction count < 30”
ELSE transaction_count>=30 THEN “Greater than or equal to 30”
END as buckets

count(*) as ct.transaction_count
FROM credit_cards c
INNER JOIN transactions t
ON c.credit_card_id = t.credit_card_id
WHERE t.status = “completed”
GROUP BY v.year_opened

GROUP BY buckets
ORDER BY buckets

Ожидаемый результат

credit card count | year opened | transaction count bucket
23421             | 2002        | Less than 10
etc

Ответы [ 3 ]

0 голосов
/ 03 июля 2018

Не уверен, что это то, что вы ищете.

WITH cte
AS (
    SELECT c.year_opened
        ,c.credit_card_id
        ,count(*) AS transaction_count
    FROM credit_cards c
    INNER JOIN transactions t ON c.credit_card_id = t.credit_card_id
    WHERE t.STATUS = 'completed'
    GROUP BY c.year_opened
        ,c.credit_card_id
    )
SELECT cte.year_opened AS 'year opened'
    ,SUM(CASE 
            WHEN transaction_count < 10
                THEN 1
            ELSE 0
            END) AS 'Less than 10'
    ,SUM(CASE 
            WHEN transaction_count >= 10
                AND transaction_count < 30
                THEN 1
            ELSE 0
            END) AS '10 <= transaction count < 30'
    ,SUM(CASE 
            WHEN transaction_count >= 30
                THEN 1
            ELSE 0
            END) AS 'Greater than or equal to 30'
FROM CTE
GROUP BY cte.year_opened

и вывод будет таким, как показано ниже.

year opened | Less than 10 | 10 <= transaction count < 30 | Greater than or equal to 30
2002        |  23421       |                              |
0 голосов
/ 03 июля 2018

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

with t1 as (
  select year_opened
     , c.credit_card_id
     , case when count(*) < 10 then 'Less than 10'
            when count(*) < 30 then 'Between [10 and 30)'
            else 'Greater than or equal to 30'
       end buckets
  from credit_cards c
  join transactions t
    on t.credit_card_id = c.credit_card_id
 where t.transaction_status = 'complete'
 group by year_opened
     , c.credit_card_id
)
select count(*) credit_card_count
     , year_opened
     , buckets
  from t1
 group by year_opened
     , buckets;

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

select count(*) credit_card_count
     , year_opened
     , buckets
  from credit_cards c
  join (select credit_card_id
             , case when count(*) < 10 then 'Less than 10'
                    when count(*) < 30 then 'Between [10 and 30)'
                    else 'Greater than or equal to 30'
               end buckets
          from transactions
         group by credit_card_id) t
    on t.credit_card_id = c.credit_card_id
 group by year_opened
     , buckets;

Если вы предпочитаете развернуть вышеупомянутый запрос и используете Common Table Expressions, вы можете сделать это тоже (мне проще читать / следовать):

with bkt as (
  select credit_card_id
       , case when count(*) < 10 then 'Less than 10'
              when count(*) < 30 then 'Between [10 and 30)'
              else 'Greater than or equal to 30'
          end buckets
    from transactions
   group by credit_card_id
)
select count(*) credit_card_count
     , year_opened
     , buckets
  from credit_cards c
  join bkt t
    on t.credit_card_id = c.credit_card_id
 group by year_opened
     , buckets;
0 голосов
/ 03 июля 2018

Вы можете указать размеры бинов в width_bucket, указав отсортированный массив нижней границы каждого бина.

В вашем случае это будет array[10,30]: все, что меньше 10, получает корзину 0, от 10 до 29 - корзину 1 и 30 или больше получает корзину 2.

WITH a AS (select generate_series(5,35) cnt)
SELECT  cnt, width_bucket(cnt, array[10,30]) 
FROM a;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...