возвращаемое значение на основе группы строк в SQL - PullRequest
0 голосов
/ 05 сентября 2018

у меня ниже данных

vid   prod
1001  other
1001  other
1001  fixed
1001  fixed
1001  other
1001  fixed
1002  other
1002  mobile
1002  mobile
1002  other
1003  other
1003  fixed
1003  other
1003  mobile
1004  fixed
1004  fixed
1005  mobile
1005  mobile

требуемый выход

vid   prod    prod_2
1001  other   fixed
1001  other   fixed
1001  fixed   fixed
1001  fixed   fixed
1001  other   fixed
1001  fixed   fixed
1002  other   mobile
1002  mobile  mobile
1002  mobile  mobile
1002  other   mobile
1003  other   fixed_mobile
1003  fixed   fixed_mobile
1003  other   fixed_mobile
1003  mobile  fixed_mobile
1004  fixed   fixed
1004  fixed   fixed
1005  mobile  mobile
1005  mobile  mobile

В основном мне нужно написать запрос, чтобы создать новый столбец 'prod_2', где фиксированный и другие, каждая строка должна быть обновлена ​​как фиксированная, если мобильный и другие должны быть мобильными, а если фиксированные, мобильные и другие, то это должен быть fixed_mobile

Ответы [ 3 ]

0 голосов
/ 07 сентября 2018

Итак, в prod_2 вам нужно:

  • 'fixed_mobile', если для данного видео существуют 'fixed' и 'mobile'

  • «исправлено», если для данного видео существует «фиксированный», но не «мобильный»

  • «мобильный», если для данного видео существует «мобильный», но не «фиксированный»

  • и, в любом другом случае, «ни то, ни другое», я полагаю, это тоже может произойти.

Я бы использовал подзапрос, сгруппированный по vid, возвращая флаги существования для каждого соответствующего продукта для vid. True больше, чем False, поэтому MAX () логического значения сообщит нам, существует ли какое-либо из искомых значений. Затем объедините основную таблицу с этим подзапросом и оцените полученные флаги, чтобы сгенерировать строку для prod_2.

Как и в этом запросе (первое общее табличное выражение - это ваш ввод, начните со второго общего табличного выражения в предложении WITH ..)

WITH 
-- this is your input, don't use it in final query                                                                                                                                                                                                  
input(vid,prod) AS (
          SELECT 1001,'other'
UNION ALL SELECT 1001,'other'
UNION ALL SELECT 1001,'fixed'
UNION ALL SELECT 1001,'fixed'
UNION ALL SELECT 1001,'other'
UNION ALL SELECT 1001,'fixed'
UNION ALL SELECT 1002,'other'
UNION ALL SELECT 1002,'mobile'
UNION ALL SELECT 1002,'mobile'
UNION ALL SELECT 1002,'other'
UNION ALL SELECT 1003,'other'
UNION ALL SELECT 1003,'fixed'
UNION ALL SELECT 1003,'other'
UNION ALL SELECT 1003,'mobile'
UNION ALL SELECT 1004,'fixed'
UNION ALL SELECT 1004,'fixed'
UNION ALL SELECT 1005,'mobile'
UNION ALL SELECT 1005,'mobile'
)
,
-- start your real WITH clause here ...
existance AS (
SELECT
  vid
, MAX(prod = 'fixed' ) AS fixed_exists
, MAX(prod = 'mobile') AS mobile_exists
FROM input
GROUP BY vid
)
SELECT 
  i.*
, CASE 
     WHEN fixed_exists AND mobile_exists THEN 'fixed_mobile'
     WHEN fixed_exists                   THEN 'fixed'
     WHEN mobile_exists                  THEN 'mobile'
     ELSE                                'none of both'
  END as prod_2
FROM input i
JOIN existance ex USING(vid)
ORDER BY i.vid
;

И вот что вы получаете:

vid  |prod  |prod_2
1,001|other |fixed
1,001|other |fixed
1,001|fixed |fixed
1,001|other |fixed
1,001|fixed |fixed
1,001|fixed |fixed
1,002|mobile|mobile
1,002|other |mobile
1,002|other |mobile
1,002|mobile|mobile 
1,003|mobile|fixed_mobile
1,003|other |fixed_mobile
1,003|other |fixed_mobile
1,003|fixed |fixed_mobile
1,004|fixed |fixed
1,004|fixed |fixed
1,005|mobile|mobile
1,005|mobile|mobile

Приятной игры ...

0 голосов
/ 10 сентября 2018

Я использовал LAG () , чтобы выполнить это в Vertica, используя временные таблицы.

CREATE LOCAL TEMPORARY TABLE IF NOT EXISTS table1
   (
      vid int
      ,prod varchar
   )
   ON COMMIT PRESERVE ROWS;

Вставьте ваши данные (vid, prod) в эту таблицу.

Создать вторую временную таблицу, добавив столбец для данных LAG ()

CREATE LOCAL TEMPORARY TABLE IF NOT EXISTS table2
   (
      vid int
      ,prod varchar
      ,prod2 varchar
   )
   ON COMMIT PRESERVE ROWS;

INSERT INTO table2
SELECT vid, prod, 
LAG(prod, 1, 0) OVER 
(PARTITION BY vid ORDER BY vid) as prod2
FROM table1
GROUP BY vid, prod
HAVING COUNT(vid) > 1
ORDER BY vid

В Table2 теперь есть все комбинации в одном ряду.

vid     prod    prod2
1001    fixed   other
1001    other   0
1002    mobile  other
1002    other   0
1003    other   0
1004    fixed   0
1005    mobile  0

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

   SELECT vid, prod, prod2,  
   CASE WHEN (((prod = 'mobile') AND (prod2 = 'fixed')) OR ((prod = 'fixed')  AND (prod2 = 'mobile'))) THEN 'fixed_mobile'
        WHEN ((prod = 'fixed'   OR   prod2 != 'mobile') OR (prod != 'mobile' AND prod2 != 'fixed')) THEN 'fixed'
        WHEN ((prod != 'fixed'   OR   prod2 = 'mobile') OR (prod = 'mobile' AND prod2 != 'fixed')) THEN 'mobile'
        ELSE 'none'
        END AS prod2
        FROM(SELECT vid, prod, prod2
     FROM table2 WHERE prod2 != '0') s1

Результаты:

vid     prod    prod2
1002    mobile  mobile
1001    fixed   none

Наконец, вы можете вставить эти данные в другую таблицу (table3) и просто выполнить простое объединение для отображения результатов:

   SELECT t1.vid, t1.prod, t2.prod3
   FROM table1 t1
   left join table3 t2
   on t2.vid = t1.vid

Очевидно, что вы могли бы достичь того же результата только с помощью подзапросов, но это кажется немного чище. Как вы можете видеть ниже, есть некоторые случаи, когда у вас есть два разных vid случая, оценивающих true. Например, vid=1003 имеет fixed, mobile и other.

vid     prod    prod3
1001    fixed   fixed
1001    fixed   fixed
1001    fixed   fixed
1001    other   fixed
1001    other   fixed
1001    other   fixed
1002    mobile  fixed
1002    mobile  fixed
1002    other   fixed
1002    other   fixed
1003    fixed   fixed
1003    fixed   fixed_mobile
1003    fixed   fixed
1003    fixed   fixed_mobile
1003    mobile  fixed
1003    mobile  fixed_mobile
1003    mobile  fixed
1003    mobile  fixed_mobile
1003    other   fixed
1003    other   fixed_mobile
1003    other   fixed
1003    other   fixed_mobile
1004    fixed   (null)
1004    fixed   (null)
1005    mobile  (null)
1005    mobile  (null)
0 голосов
/ 05 сентября 2018

Я думаю, вы должны использовать union all в соответствии с условием

select vid,prod,'fixed' as prod2 from t1 where
  t1.vid in(
     select vid from t1     
      where prod in ('fixed','other')
      and vid not in
      (select vid from t1     
      where prod in ('fixed','mobile','other')
      having count(distinct prod )>=3
      group by vid
      )
      having count(distinct prod )>=2
      group by vid
     ) 
union all

select vid,prod,'mobile' as prod2 from t1 where
  t1.vid in(
     select vid from t1     
      where prod in ('mobile','other')
      having count(distinct prod )>=2
      group by vid
     ) 
union all
select vid,prod,'fixed_mobile' as prod2 from t1 where
  t1.vid in(
     select vid from t1     
      where prod in ('fixed','mobile','other')
       and vid not in
       (
        select vid from t1     
      where prod in ('fixed','other')
      having count(distinct prod )>=2
      group by vid
       )
      having count(distinct prod )>=3
      group by vid
     )
...