基于Group by的SQL查询,需要基于min和max的派生列

时间:2017-05-03 21:53:34

标签: sql sql-server tsql

Create table test123 (
    CustId int,
    [Level]  int,
    RowNum int,
    USAFlag bit
)

insert into test123(CustId,[Level],RowNum,USAFlag)values
(101,1,1,0),
(102,2,1,0),
(102,2,2,1),
(103,3,1,0),
(103,3,2,1),
(103,3,3,0),
(104,4,1,1),
(104,4,2,0),
(104,4,3,0),
(104,4,4,1),
(105,2,1,1),
(105,2,2,0),
(106,2,1,0),
(106,2,2,0),
(107,3,1,0),
(107,3,2,0),
(107,3,3,1),
(108,1,1,1)

输出

CustID USARootLeaf
101 ONlyONeLevel_NonUSA
102 Leaf_USA
103 Root_Leaf_NonUSA
104 Root_Leaf_USA
105 Root_USA
106 Root_Leaf_NonUSA
107 Leaf_USA
108 OnlyOneLvel_USA

逻辑: 如果Level为1,则USARootLeaf值应为OnlyOneLvel_USA或OnlyOneLvel_NonUSA,基于USAFlag值

如果Level为> 1,则USARootLeaf值应为Root_Leaf_USA,Root_Leaf_NonUSA,Root_USA,Leaf_USA基于min(级别)和USAFlag的max(level)值为true / false

2 个答案:

答案 0 :(得分:0)

这可以重构为更小,但这里是根据上述要求对实现的猜测。 请注意,我在我的DDL中将[Level]更改为thisLevel。

mysql> select q.custid, concat(q.type,concat('_',q.starsandstripes)) as type from (
    -> select
    ->        z.custid,
    ->        case when minlevel = 1 and maxlevel = 1 then 'OnlyOneLevel'
    ->        else 
    ->           case when lastflag = 1 and firstflag = 0 then 'Leaf'
    ->           when lastflag = 0 and firstflag = 1 then 'Root'
    ->           when lastflag = firstflag then 'Root_Leaf'
    ->           end
    ->        end as type,
    ->        starsandstripes
    ->        from 
    -> (
    -> select 
    ->    za.custid,
    ->    case when max(za.usaflag) = 1
    ->       then 'USA' 
    ->       else 'NonUSA' 
    ->    end
    ->      as starsAndStripes
    -> from test123 za join
    ->     (
    ->         select 
    ->            custid, 
    ->            max(rownum) as maxrow, 
    ->            min(rownum) as minrow
    ->         from test123 zc
    ->         group by custid
    ->     ) zb 
    ->     on za.custid = zb.custid 
    ->       and (za.rownum = zb.maxrow
    ->       or za.rownum = zb.minrow)
    -> group by za.custid
    -> ) z,
    -> (
    ->    select
    ->       a.custid,
    ->       (select usaflag from test123 d where d.custid = a.custid and d.rownum = b.maxrow) as lastFlag,
    ->       (select usaflag from test123 d where d.custid = a.custid and d.rownum = b.minrow) as firstFlag,
    ->       min(thisLevel) as minLevel,
    ->       max(thisLevel) as maxLevel
    ->    from test123 a join
    ->    (
    ->        select custid, max(rownum) as maxrow, min(rownum) as minrow
    ->        from test123 c
    ->        group by custid
    ->    ) b 
    ->    on a.custid = b.custid
    ->    group by custid,
    ->    (select usaflag from test123 d where d.custid = a.custid and d.rownum = b.maxrow),
    ->    (select usaflag from test123 d where d.custid = a.custid and d.rownum = b.minrow)
    -> ) x
    ->    where z.custid = x.custid
    -> ) q;

输出:

+--------+---------------------+
| custid | type                |
+--------+---------------------+
|    101 | OnlyOneLevel_NonUSA |
|    102 | Leaf_USA            |
|    103 | Root_Leaf_NonUSA    |
|    104 | Root_Leaf_USA       |
|    105 | Root_USA            |
|    106 | Root_Leaf_NonUSA    |
|    107 | Leaf_USA            |
|    108 | OnlyOneLevel_USA    |
+--------+---------------------+
8 rows in set (0.00 sec)    

答案 1 :(得分:0)

感谢Bryan和Jason的快速投入。 我自己找到了一个更好的解决方案。

with one as
(
Select CustId,[Level],
STUFF((SELECT ',' + cast(USAFlag as char(1)) FROM test123 WHERE (
CustId=Result.CustId) FOR XML PATH ('')),1,1,'') AS USAList
From test123 AS Result
GROUP BY CustId,[Level]
)
Select CustId,[level],USAList,
case 
when Level=1 and substring(USAList,1,1)='1' then 'ONlyONeLevel_USA'
when Level=1 and substring(USAList,1,1)='0' then 'ONlyONeLevel_NonUSA'
when Level>1 and substring(USAList,1,1)='1' and substring(USAList,level*2-
1,1)='1' then 'Root_Leaf_USA'
when Level>1 and substring(USAList,1,1)='0' and substring(USAList,level*2-
1,1)='0' then 'Root_Leaf_NonUSA'
when Level>1 and substring(USAList,1,1)='1'  then 'Root_USA'
when Level>1 and substring(USAList,level*2-1,1)='1'  then 'Leaf_USA'
else 'InvalidLevel'
end as USARootLeaf
from one