Разделение с условием - PullRequest
       22

Разделение с условием

1 голос
/ 08 апреля 2020

У меня есть данные о товарах, которые продаются в разных магазинах. Для некоторых магазинов они продаются со скидкой PROMO_FLG. Я хотел бы отобразить два COUNT PARTITION столбца.

+-------------------------+--------------+---------------------+
| Store                   | Item         | PROMO_FLG|
|-------------------------+--------------+---------------------|
| 1                       |            1 |                   0 |
| 2                       |            1 |                   1 |
| 3                       |            1 |                   0 |
| 4                       |            1 |                   0 |
| 5                       |            1 |                   1 |
| 6                       |            1 |                   1 |
| 7                       |            1 |                   1 |
| 8                       |            1 |                   0 |
| 9                       |            1 |                   0 |
| 10                      |            1 |                   0 |
+-------------------------+--------------+---------------------+

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

COUNT(DISTINCT STORE) OVER (PARTITION ITEM) даст 10

Второй - который я ищу - учитывает только те магазины, которые имеют значение в атрибуте PROMO_FLG = 1.

Это должно дать нам значение 4

Ответы [ 2 ]

3 голосов
/ 08 апреля 2020

Я думаю, что вы хотите:

select t.*,
       count(*) over (partition by item) as num_stores,
       sum(promo_flg) over (partition by item) as num_promo_1
from t;

Если вам действительно нужны разные значения:

select t.*,
       count(distinct store) over (partition by item) as num_stores,
       count(distinct case when promo_flg = 1 then store end) over (partition by item) as num_promo_1
from t;

Здесь - это дб <> скрипка. Скрипт использует Oracle, потому что он поддерживает COUNT(DISTINCT) в качестве оконной функции.

Вот альтернатива, если оконные функции не работают:

select *
from t join
     (select item, count(distinct store) as num_stores, count(distinct case when promo_flg = 1 then store end) as num_stores_promo
      from t
      group by item
     ) tt
     using (item);
1 голос
/ 09 апреля 2020

, используя Гордона в секунду SQL, но показывая, что он работает в Снежинке

select v.*
    ,count(distinct store) over (partition by item) as num_stores
    ,count(distinct iff(promo_flg = 1, store, null)) over (partition by item) as num_dis_promo_stores
    ,sum(iff(promo_flg = 1, 1, 0)) over (partition by item) as num_sum_promo_stores
from values
  (1 , 1, 0 ),
  (2 , 1, 1 ),
  (3 , 1, 0 ),
  (4 , 1, 0 ),
  (5 , 1, 1 ),
  (6 , 1, 1 ),
  (7 , 1, 1 ),
  (8 , 1, 0 ),
  (9 , 1, 0 ),
  (10, 1, 0 )
  v(store, item, promo_flg) ;

, дает:

STORE   ITEM    PROMO_FLG   NUM_STORES  NUM_DIS_PROMO_STORES    NUM_SUM_PROMO_STORES
1       1       0           10          4                       4
2       1       1           10          4                       4
3       1       0           10          4                       4
4       1       0           10          4                       4
5       1       1           10          4                       4
6       1       1           10          4                       4
7       1       1           10          4                       4
8       1       0           10          4                       4
9       1       0           10          4                       4
10      1       0           10          4                       4

Таким образом, в зависимости от того, хотите ли вы отдельный счет или сумму, оба, Я использовал нестандартную форму SQL, которая поддерживает снежинку iff, так как я предпочитаю, чтобы она была меньше sql. Но вы можете видеть их работу.

тестирование второго случая Гордона count(distinct case when promo_flg = 1 then store end) over (partition by item) as num_promo_1 работает как написано.

Чтобы ответить на вопрос Marcin2x4 об ответе Гордона, вы получите разные результаты от методов, если / когда данные отклоняются от того, как вы описали Это. Таким образом, в случае, если у вас есть магазин, есть элемент и несколько строк с promo_flg. Или, если promo_flg имеет ненулевые значения:

select v.*
    ,count(distinct store) over (partition by item) as num_stores
    ,count(distinct iff(promo_flg = 1, store, null)) over (partition by item) as num_dis_promo_stores
    ,sum(iff(promo_flg <> 0, 1, 0)) over (partition by item) as num_sum_promo_stores
    ,sum(promo_flg) over (partition by item) as num_promo_1
    ,count(distinct case when promo_flg = 1 then store end) over (partition by item) as num_promo_1
from values
  (1 , 1, 0 ),
  (2 , 1, 1 ),
  (3 , 1, 0 ),
  (4 , 1, 0 ),
  (5 , 1, 1 ),
  (6 , 1, 1 ),
  (7 , 1, 1 ),
  (8 , 1, 0 ),
  (9 , 1, 0 ),
  (10, 1, 0 ),
  (7, 1, 1 ),
  (7, 1, 2 )
  v(store, item, promo_flg) ;

, тогда num_dis_promo_stores & num_promo_1 дает 4, num_sum_promo_stores дает 6, & num_promo_1 дает 7

...