【问题标题】:Oracle- count the number rows based on a conditionOracle-根据条件计算行数
【发布时间】:2020-09-24 09:09:37
【问题描述】:

我想创建一个“票证”,用于计算每个 ID 的通行证次数。当我们在任何 ID 上拥有黄金通行证时,这意味着该通行证适用于所有预订的人。所以对于这个例子,我们想要计算 5。对于其他 pass_codes,我们想要简单地计算 pass 的数量并排除那些为 null 的。我在下面有一个预期的输出。

假设我有这些数据:

 Passes
    ID   | GuestID |  Pass_code
    ----------------------------
    100  |   001   | Bronze 
    100  |   002   | Bronze 
    101  |   103   | Gold
    101  |   104   | NULL
    101  |   105   | NULL
    101  |   106   | NULL
    101  |   107   | NULL
    102  |   208   | Silver
    103  |   209   | Steel
    103  |   210   | Steel
    103  |   211   | NULL
    
    Passengers
    ID   |  Passengers
    -----------------
    100  |  2
    101  |  5
    102  |  1
    103  |  3
    

我想计算然后在输出中创建一张票:

    ID 100 | 2 pass (bronze)
    ID 101 | 5 pass (because it is gold, we count all passengers)
    ID 102 | 1 pass (silver)
    ID 103 | 2 pass (steel) (2 passes rather than than 3 as we just want to count only the passes for steel, bronze silver)

我想做这样的事情,但作为一个组合查询。

DECLARE @ID = 101; -- i will want to pass in IDs 

   -- for gold, we want to count all passengers when the gold pass is on 
   SELECT pp.Passengers
                 FROM passes
                 JOIN Passengers pp ON p.ID = pp.ID
                 WHERE p.pass_code IN'%gold%'
                 AND PP.id = @id

  -- for bronze, silver and steel
  SELECT 
       count(p.ID)
  FROM Passes
  WHERE p.ID = @id
  AND P.pass_code IN ('Bronze', 'silver', 'steel') -- Dont want to check based on NUlls as this may chnage to something else.

)

任何帮助或建议将不胜感激。

【问题讨论】:

    标签: oracle plsqldeveloper


    【解决方案1】:

    这对你有用吗?

    with Passes as (
    select  100 as id, 001  as guestid, 'Bronze' as passcode from dual union all
    select  100 as id, 002  as guestid, 'Bronze' as passcode from dual union all
    select  101 as id, 103  as guestid,'Gold'   as passcode from dual union all
    select  101 as id, 104  as guestid, NULL   as passcode from dual union all
    select  101 as id, 105  as guestid, NULL   as passcode from dual union all
    select  101 as id, 106  as guestid, NULL   as passcode from dual union all
    select  101 as id, 107  as guestid, NULL   as passcode from dual union all
    select  102 as id, 208  as guestid, 'Silver' as passcode from dual union all
    select  103 as id, 209  as guestid, 'Steel'  as passcode from dual union all
    select  103 as id, 210  as guestid, 'Steel'  as passcode from dual union all
    select  103 as id, 211  as guestid, NULL   as passcode from dual
    )
    SELECT 
      id,passcode,count(ID)
      FROM Passes
      where passcode is not null and passcode<>'Gold'
      group by id,passcode
       union all
     SELECT 
         id,'Gold',count(ID)
      FROM Passes
      where id in 
       (
      select id from Passes where  passcode='Gold' 
      ) 
      group by id
      order by id
    

    结果:

    100 Bronze  2
    101 Gold    5
    102 Silver  1
    103 Steel   2
    

    【讨论】:

      【解决方案2】:

      如果我正确理解您的问题,则查询应如下所示

      ** 表格

      create table test (ID number, GuestId number, Pass_code varchar2(10));
      insert into test values(100,001,'Bronze');
      insert into test values(100,002,'Bronze');
      insert into test values(101,103,'Gold');
      insert into test values(101,104,NULL);
      insert into test values(101,105,NULL);
      insert into test values(101,106,NULL);
      insert into test values(101,107,NULL);
      insert into test values(102,208,'Silver');
      insert into test values(103,209,'Steel');
      insert into test values(103,210,'Steel');
      insert into test values(103,211,NULL);
      commit;
      
      
      SQL> select * from test order by 1,2;
      
              ID    GUESTID PASS_CODE
      ---------- ---------- ------------------------------
             100          1 Bronze
             100          2 Bronze
             101        103 Gold
             101        104
             101        105
             101        106
             101        107
             102        208 Silver
             103        209 Steel
             103        210 Steel
             103        211
      
      11 rows selected.
      

      ** 查询

      WITH PASSES AS (
      SELECT T1.ID,T1.PASS_CODE, COUNT(T2.ID) QUANTITY FROM TEST T1, TEST T2
      WHERE T1.PASS_CODE='Gold' AND T1.ID=T2.ID
      GROUP BY T1.ID,T1.PASS_CODE
      UNION ALL
      SELECT ID,PASS_CODE, COUNT(*) QUANTITY FROM TEST
      WHERE PASS_CODE IS NOT NULL AND 
            PASS_CODE != 'Gold'
      GROUP BY ID,PASS_CODE)
      SELECT ID, QUANTITY || ' (' || PASS_CODE || ')' RESULT FROM PASSES
      ORDER BY ID;
      

      ** 结果

              ID RESULT
      ---------- --------------------
             100 2 (Bronze)
             101 5 (Gold)
             102 1 (Silver)
             103 2 (Steel)
      

      【讨论】:

      • 感谢您的回答。我也对我们如何通过传入单个@id 来做到这一点感兴趣。我通过具有类似解决方案的 cte 实现了这一点,然后选择了 max(count)。