Redshift, Найти распределение уровней каждого элемента (общее количество элементов на уровень) - PullRequest
1 голос
/ 07 октября 2019

Вопрос обновлен !!

У меня есть база данных, в которой хранится обновление предмета клиента. У меня есть DateTime и обновленный уровень. Когда клиент обновляет элемент в день 1 и снова в день 5, я не вижу никакой информации между Днем 1-Днем 5

Пример данных: (таблица обновлений)

 day              customer    items        levels
01/01/2019           a          item1          0
01/01/2019           b          item1          0
02/01/2019           a          item1          1
03/01/2019           b          item1          1
04/01/2019           a          item1          2
05/01/2019           b          item1          2
05/01/2019           c          item1          0
06/01/2019           b          item1          3
07/01/2019           d          item2          0
08/01/2019           NULL       NULL          NULL
09/01/2019           b          item1          4
10/01/2019           NULL       NULL          NULL
11/10/2019           b          item1         5
11/10/2019           a          item1         3
11/10/2019           a          item1         4

Пример данных: (ежедневная таблицадля пользователя)

 day              time-spent      
01/01/2019           11       
02/01/2019           34        
03/01/2019           56        
04/01/2019           78       
11/01/2019           3         
14/01/2019           13
22/01/2019           30        

Моя задача - найти общее количество предметов для каждого уровня, так что Level 0 item-1 у меня в день:

01/01/2019     2            
02/01/2019     1      
03/01/2019     0     
04/01/2019     0      
05/01/2019     1             
06/01/2019     1     
07/01/2019     1      
08/01/2019     1     
09/01/2019     1      
10/01/2019     1      
11/10/2019     1      

Какмного Level 1 предмет-1 у меня в день?

01/01/2019     0            
02/01/2019     1      
03/01/2019     2     
04/01/2019     1      
05/01/2019     0             
06/01/2019     0     
07/01/2019     0      
08/01/2019     0     
09/01/2019     0      
10/01/2019     0      
11/10/2019     0  

за все двадцать уровней на предмет! (Мне нужно найти уровень распределения предметов!)

Что я пробовал это:

    SELECT *
    FROM (
           SELECT date(timestamp) day,
                  user_id,
                  item_id,
                  level,
-- Left join the daily table and get last value of an item per customers
                  last_value(level) IGNORE NULLS OVER (PARTITION BY user_id ORDER BY day
                    ROWS UNBOUNDED PRECEDING ) level_r
           FROM daily d -- I have a calendar dates from and all customers in this table 
                  LEFT JOIN (
               SELECT user_id,
                      date(TIMESTAMP) t,
                      item_id,
                      level,
                      RANK()
                      OVER (PARTITION BY user_id,date(timestamp), item_id ORDER BY TIMESTAMP DESC ) transaction_rank
               FROM updated 
               WHERE item_id
             ) u ON u.user_id = d.user_id AND u.t = d.day AND transaction_rank = 1
           GROUP BY
             1, 2, 3, 4)

, но проблема в том, что он работает, если у меня есть один клиент из-за нулевых значений, но еслиу вас есть несколько клиентов, это не работает.

Как я могу найти распределение уровней для предметов?

РЕДАКТИРОВАТЬ: Я хотел бы добавить больше информации, чтобы сделать более понятным. Если никто не меняет уровень своего предмета в предыдущий день, мне нужно знать также и следующий день.

Мне нужно знать, сколько уровней предмета у меня есть от любой выбранной даты до предыдущего целого времени

РЕДАКТИРОВАТЬ-2: Мне не нужно присоединяться к таблице обновления до ежедневного. Мне нужно, чтобы все значения таблицы обновлений приводили в типе generate_series, но когда я создаю Generate Seres, у меня появляется ошибка

Ответы [ 3 ]

0 голосов
/ 17 октября 2019

Если у вас есть хотя бы одна строка в день, тогда это выглядит как агрегация:

select timestamp::date,
       sum( (level = 1)::int ) as level_1,
       sum( (level = 2)::int ) as level_2,
       . . . 
       sum( (level = 20)::int ) as level_20
from daily
group by timestamp::date
order by timestamp::date;
0 голосов
/ 23 октября 2019

Давайте начнем с создания базового запроса, который дает нам текущий уровень каждого клиента на каждый день.

Это работает, восстанавливая все доступные дни в таблице, затем все предыдущие записи по каждому дню и, наконец, агрегируя для вычисления текущего уровня каждого (customer, item) кортежа.

Основное предположение заключается в том, что уровень кортежа не может снизиться (это согласуется с вашими выборочными данными).

select
    d.day,
    t.customer, 
    t.items,
    max(t.levels) max_level
from 
    (select distinct day from mytable) d
    left join mytable t on t.day <= d.day
group by 
    d.day, 
    t.customer, 
    t.items

С этого момента довольно легко сгенерироватьтребуемый результат путем добавления другого уровня (условного) агрегирования.

Этот запрос дает распределение клиентов item1 в день по уровням от 1 до 5:

select 
    day,
    sum( (max_level = 0)::int ) level0,
    sum( (max_level = 1)::int ) level1,
    sum( (max_level = 2)::int ) level2,
    sum( (max_level = 2)::int ) level3,
    sum( (max_level = 4)::int ) level4,
    sum( (max_level = 5)::int ) level5
from (
    select
        d.day,
        t.customer, 
        t.items,
        max(t.levels) max_level
    from 
        (select distinct day from mytable) d
        left join mytable t on t.day <= d.day
    group by 
        d.day, 
        t.customer, 
        t.items
) x
where items = 'item1'
group by day
order by day

Доходность:

| day                      | level0 | level1 | level2 | level3 | level4 | level5 |
| ------------------------ | ------ | ------ | ------ | ------ | ------ | ------ |
| 2019-01-01T00:00:00.000Z | 2      | 0      | 0      | 0      | 0      | 0      |
| 2019-02-01T00:00:00.000Z | 1      | 1      | 0      | 0      | 0      | 0      |
| 2019-03-01T00:00:00.000Z | 0      | 2      | 0      | 0      | 0      | 0      |
| 2019-04-01T00:00:00.000Z | 0      | 1      | 1      | 1      | 0      | 0      |
| 2019-05-01T00:00:00.000Z | 1      | 0      | 2      | 2      | 0      | 0      |
| 2019-06-01T00:00:00.000Z | 1      | 0      | 1      | 1      | 0      | 0      |
| 2019-07-01T00:00:00.000Z | 1      | 0      | 1      | 1      | 0      | 0      |
| 2019-08-01T00:00:00.000Z | 1      | 0      | 1      | 1      | 0      | 0      |
| 2019-09-01T00:00:00.000Z | 1      | 0      | 1      | 1      | 1      | 0      |
| 2019-10-01T00:00:00.000Z | 1      | 0      | 1      | 1      | 1      | 0      |
| 2019-11-10T00:00:00.000Z | 1      | 0      | 0      | 0      | 1      | 1      |

Демонстрация на DB Fiddle

0 голосов
/ 07 октября 2019

Это то, что вы хотите

Select * from 
(Select Day,items,levels,count(*) from dataa group by 
               day,items,levels )
 pivot (count(*) for levels in (0,1,2,3,4,5)) order by day,items;

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...