Поиск значения в строке в PostgreSQL - PullRequest
0 голосов
/ 27 сентября 2019

У меня есть веб-сайт, работающий на Magento (1.9), и у меня есть требование выяснить среднее время, которое покупатель тратит на покупку того же продукта снова, и процент покупателей, купивших тот же продукт.

Таблица заказов (Sales_flat_order) - Содержит детали заказа. Столбцы - order_id, Created_date, Customer_email

Таблица товаров (Sales_Flat_Order_item) - Товары в определенном порядке. Если пользователь купит 6 товаров, то таблица товаров будет иметь 6 записей стот же код заказа.Столбцы - items_id, Order_id (FK), item_sku (различаются для разных продуктов)

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

Например, order_id "92224" содержит 4 строки, что означает, что в этом заказе было приобретено 4 элемента, а item_sku ссылается на имя элемента / его уникальный идентификатор.

Теперь я хочу узнать среднее время, затрачиваемое начтобы купить тот же товар снова. Так что в заказе "98651" пользователь приобрел продукт items_sku ("2996"), который был там в первом заказе. Таким образом, среднее время будет разницей в датах между этими двумя заказами.

Ниже приведены трудности, с которыми я сталкиваюсь,

1) Поскольку каждый заказ может содержать несколько продуктов, как я могу сравнить ряд элементов с элементами предыдущего заказа. Я пробовал с LIKE & ILIKE икажется, что он не работает и пытался использовать STR_AGG (item_sku, ',') с LIKE, но не нашел никакого результата.

2) Не только для определенного cКак правило, это необходимо сделать для каждого клиента.

Order_id     Order_date         Item_sku
92224   "2016-11-11 17:18:15"   "3001"
92224   "2016-11-11 17:18:15"   "2933"
92224   "2016-11-11 17:18:15"   "2992-config"
92224   "2016-11-11 17:18:15"   "2996"
94926   "2016-11-25 10:01:30"   "3008"
98651   "2016-12-14 18:11:16"   "2992-config"
98651   "2016-12-14 18:11:16"   "2996"
99645   "2016-12-20 13:00:34"   "3001"
99645   "2016-12-20 13:00:34"   "2933"
114578  "2017-02-28 15:32:54"   "2931"
114578  "2017-02-28 15:32:54"   "0294"
114578  "2017-02-28 15:32:54"   "0297"
114578  "2017-02-28 15:32:54"   "0296"
114578  "2017-02-28 15:32:54"   "2992-config"
131754  "2017-05-15 17:23:35"   "3296"
131968  "2017-05-16 18:30:52"   "3300"
133186  "2017-05-22 14:03:07"   "3004"
133186  "2017-05-22 14:03:07"   "3069-bio"
133186  "2017-05-22 14:03:07"   "3421-bio-config"
137484  "2017-06-13 14:07:28"   "3605"
137484  "2017-06-13 14:07:28"   "3604"
141709  "2017-07-03 16:20:30"   "3603"
141709  "2017-07-03 16:20:30"   "3606"
141709  "2017-07-03 16:20:30"   "2936"
141709  "2017-07-03 16:20:30"   "3422-bio"
141977  "2017-07-04 16:31:37"   "2936"
145194  "2017-07-17 15:22:41"   "3603"
145194  "2017-07-17 15:22:41"   "3604"
151651  "2017-08-11 11:43:38"   "3809"
161334  "2017-09-14 15:53:30"   "3670"
161334  "2017-09-14 15:53:30"   "3604"
161334  "2017-09-14 15:53:30"   "3603"

Любое руководство будет очень полезным. Я использую PostgreSQL в качестве базы данных.

Ответы [ 2 ]

2 голосов
/ 28 сентября 2019

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

select item_sku
     , extract('days' from average_time) || ' days ' ||  extract('hour' from average_time) || ' hours' average_time
  from (    
        select item_sku,avg(intv) average_time   
          from (
                select order_date, 
                       item_sku, 
                       (order_date - lag(order_date) 
                                     OVER (partition by item_sku order by order_date)) as intv
                  FROM sales_flat_order_item
               ) intv_diff
         where intv is not null
         group by item_sku
         order by item_sku) avg_time; 

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

1 голос
/ 27 сентября 2019

Я ничего не знаю о magento, но именно так я бы решил эту проблему в postgres, учитывая ваши входные данные:

SELECT item_sku, avg(elapsed_s) as avg_s
FROM (
  select order_id, 
         order_date, 
         item_sku, 
         extract(epoch from (order_date - lag(order_date) 
            OVER (partition by item_sku order by order_date))) as elapsed_s
  FROM orders
) sub
WHERE elapsed_s IS NOT NULL
GROUP BY item_sku
;
  item_sku   |    avg
-------------+-----------
 2933        |   3354139
 2936        |     87067
 2992-config | 4705639.5
 2996        |   2854381
 3001        |   3354139
 3603        |   3152790
 3604        |   4020781
(7 rows)

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

Если вы добавляете несколько пользователей, вы просто измените предложение partition by на partition by user_id, item_sku, а затем сгруппируете по user_id и item_sku.

...