基于sql中的行组返回值

时间:2018-09-05 07:05:38

标签: sql vertica

我有以下数据

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 :(得分:0)

我认为您必须根据条件使用全部工会

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
     )

答案 1 :(得分:0)

因此,在prod_2中,您需要:

  • “ fixed_mobile”,如果给定vid存在“ fixed”和“ mobile”

  • 对于给定的视频,如果存在“固定”但没有“移动”,则
  • 为“固定”

  • “移动”,如果给定vid存在“移动”但不“固定”的情况

  • 我认为
  • 以及在其他任何情况下“两者都不存在”。

我将使用按vid分组的子查询,为每个vid返回每个相关产品的存在标志。 True大于False,因此布尔值的MAX()会告诉我们是否存在任何搜索到的值。然后,将主表与该子查询连接,并评估获得的标志以生成prod_2的字符串。

像该查询一样(第一个Common Table Expression是您的输入,从WITH子句中的第二个Common Table Expression开始。)

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

玩得开心...

答案 2 :(得分:0)

我使用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具有fixedmobileother

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)