复杂的计数查询

时间:2014-03-07 10:35:15

标签: tsql

感谢您的回答

但是我认为我的所需输出混乱了。 这就是我想要的(因为我正在使用ORacle DB)

创建表TestTable (   Bill_date DATE,   Phone_no NUMBER(10),   Planlvl1 VARCHAR2(20),   Planlvl2 VARCHAR2(20)   收入NUMBER

INSERT INTO TestTable 值 ('1/01/2014',64221,'Bundle','SpecialPack1','$ 23'), ('1/01/2014'',64221,'Bundle','PlanA','$ 32'), ('1/01/2014',65211,'Bundle','SpecialPack2','$ 3'), ('1/01/2014',65211,'Bundle','SpecialPack1','$ 23'), ('1/01/2014',66211,'Bundle','PlanB','$ 34'), ('1/01/2014',66211,'Bundle','SpecialPack2','$ 3'), ('1/01/2014',66222,'Bundle','SpecialPack1','$ 23'), ('1/01/2014',66222,'Bundle','SpecialPack2','$ 3'), ('1/01/2014',66222,'Bundle','PlanB','$ 65'), ('1/01/2014',32444,'Non_bundle','Casual1','$ 32'), ('1/01/2014',324441,'Non_bundle','Casual2','$ 76'), ('1/01/2014',65444,'Non_bundle','Casual1','$ 12'), ('1/01/2014',65444,'Bundle','PlanB','$ 98'), ('1/01/2014',54322,'Bundle','PlanA','$ 12'), ('1/01/2014',54322,'Non_bundle','休闲','12美元')

预期结果: Bill_date PlanLvl2 PhonenoCount '01 / 01 / 2014''FitialPack1'1

'01 / 01/2014''SpecialPack2'3

'01 / 01/2014''Casual1'1

'01 / 01/2014''Casual2'1

'01 / 01/2014''PlanA'1

'01 / 01/2014''PlanB'1

正如我所提到的,如果手机没有这两款产品,'SpecialPack2'将优先于特殊包装1。

希望它更清楚

基本上最昂贵的计划计数逻辑适用于手机没有超过1'特殊包'并且没有其他类型的计划的情况。 如果电话没有特殊包装和其他计划,那么我们不需要根据“非特殊”计划计算电话号码。

我有一个测试表如下

CREATE TABLE TestTable
 (`Bill_date` datetime, `Phone_no` int, `Planlvl1` varchar(10), `PlanLvl2` varchar(12), `revenue` varchar(3))
;

INSERT INTO TestTable
 (`Bill_date`, `Phone_no`, `Planlvl1`, `PlanLvl2`, `revenue`)
VALUES
 ('2014-01-01 13:00:00', 64221, 'Bundle', 'SpecialPack1', '$23'),
 ('2014-01-01 13:00:00', 64221, 'Bundle', 'PlanA', '$32'),
 ('2014-01-01 13:00:00', 65211, 'Bundle', 'SpecialPack2', '$3'),
 ('2014-01-01 13:00:00', 65211, 'Bundle', 'SpecialPack1', '$23'),
 ('2014-01-01 13:00:00', 66211, 'Bundle', 'PlanB', '$34'),
 ('2014-01-01 13:00:00', 66211, 'Bundle', 'SpecialPack2', '$3'),
 ('2014-01-01 13:00:00', 66222, 'Bundle', 'SpecialPack1', '$23'),
 ('2014-01-01 13:00:00', 66222, 'Bundle', 'SpecialPack2', '$3'),
 ('2014-01-01 13:00:00', 66222, 'Bundle', 'PlanB', '$65'),
 ('2014-01-01 13:00:00', 32444, 'Non_bundle', 'Casual1', '$32'),
 ('2014-01-01 13:00:00', 324441, 'Non_bundle', 'Casual2', '$76'),
 ('2014-01-01 13:00:00', 65444, 'Non_bundle', 'Casual1', '$12'),
 ('2014-01-01 13:00:00', 65444, 'Bundle', 'PlanB', '$98'),
 ('2014-01-01 13:00:00', 54322, 'Bundle', 'PlanA', '$12'),
 ('2014-01-01 13:00:00', 54322, 'Non_bundle', 'Casual', '$12')
;

基本上我必须以某种方式计算按计划分组的所有电话号码:

如果PlanLvl1 = Bundle,那么我必须查看planLvl2并查看该手机是否没有'SpecialPack%',还有另一个计划,他们'特殊包'获得优先权并且手机没有计入特殊包

如果PlanLvl1 = Bundle并且手机没有“特殊包装”作为他们的计划,那么手机号码将被计入“特别包”以及更高的收入。

如果PalnLvl是'Bundle'并且手机没有多个'Special Packs'且非特殊包,那么ph no只会在'Special Pack'下计算一次;与较低转速的特殊包装相比,转速更高。

现在还有PlanLvl1,它们是'Non_Bundles',这意味着它们没有任何'SpecialPacks',但是如果带有'NonBundle'计划的ph值在planLvl2下有2个不同的计划,我们需要计算eack planLvl2的ph值..

然后有一个场景,其中一个ph不能有捆绑和非捆绑,在这种情况下,我们只需要计算捆绑中的ph值,而不是非捆绑。

这是预期的结果:

Bill_date PlanLvl2 PhonenoCount

01/01/2014 SpecialPack1 3

01/01/2014 SpecialPack2 1

01/01/2014 Casual1 0

01/01/2014 Casual2 1

01/01/2014 PlanA 1

01/01/2014 PlanB 1

1 个答案:

答案 0 :(得分:0)

试试这个fiddle,注意没有“SpecialPack2”,因为所有数字都有SpecialPack1和聚合值忽略空值,所以不返回零。

注意问题不是聚合,而是“不计算此”逻辑。 另外我注意到大多数这个逻辑只计算最昂贵的计划,在这种情况下逻辑可以简化很多。 顺便说一下,将这些值保持为字符串(并带有前导'$')是一种非常糟糕的做法。

select bill_date
, case 
when planlvl1 = 'Bundle' and planlvl2 like 'SpecialPack%' then planlvl2
when planlvl1 = 'Bundle' then planlvl2
when planlvl1 = 'Non_bundle' then planlvl2
else planlvl1 end as PlanLvl2
, count(phone_no) as PhonenoCount
from
(
select Bill_date, Phone_no, Planlvl1, PlanLvl2, cast(substring(revenue, 2, 20) as float) as revenue
  from testTable
  where 
  (
    planlvl1 = 'Bundle'
    and 
    ( 
      (planlvl2 like 'SpecialPack%'
        and cast(substring(revenue, 2, 20) as float) = (select max(cast(substring(t1.revenue, 2, 20) as float)) from testTable t1 where t1.phone_no = phone_no and planlvl2 like 'SpecialPack%')
       )
     or
     (planlvl2 not like 'SpecialPack%'
      and phone_no not in (select phone_no from testTable where planlvl2 like 'SpecialPack%')
      )
    )
  )
  or (planlvl1 = 'Non_bundle' and phone_no not in (select phone_no from testTable where Planlvl1 = 'Bundle')
      and cast(substring(revenue, 2, 20) as float) = (select max(cast(substring(t1.revenue, 2, 20) as float)) from testTable t1 where t1.phone_no = phone_no and planlvl1 = 'Non_bundle')
     )

) as ignore_duplicates
group by bill_date
, case 
when planlvl1 = 'Bundle' and planlvl2 like 'SpecialPack%' then planlvl2
when planlvl1 = 'Bundle' then planlvl2
when planlvl1 = 'Non_bundle' then planlvl2
else planlvl1 end