【问题标题】:Most efficient way to pivot multiple groups over multiple columns using Oracle SQL?使用 Oracle SQL 在多个列上旋转多个组的最有效方法?
【发布时间】:2020-08-28 21:11:20
【问题描述】:

任何人都可以帮助确定使用 Oracle SQL 在多个组中、跨多个列中透视数据的最有效方法吗?

我有一张如下表:

NAME    MEAL    FOOD    DRINK
Dan     Lunch   Taco    Coke
Dan     Dinner  Steak   Water
Becky   Lunch   Pizza   Coke
Becky   Dinner  Pizza   Milk

而我想要的输出如下表:

NAME    LUNCH_FOOD    LUNCH_DRINK    DINNER_FOOD    DINNER_DRINK
Dan     Taco          Coke           Steak          Water
Becky   Pizza         Coke           Pizza          Milk

执行此操作的最佳方法是什么?我下面的解决方案完成了任务,但我觉得有一种更有效的方法:

数据:

CREATE TABLE EXAMPLE (PERSON VARCHAR(10), MEAL VARCHAR(10), FOOD VARCHAR(10), DRINK VARCHAR(10));

INSERT INTO EXAMPLE (PERSON, MEAL, FOOD, DRINK) VALUES ('Dan', 'Lunch', 'Taco', 'Coke');
INSERT INTO EXAMPLE (PERSON, MEAL, FOOD, DRINK) VALUES ('Dan', 'Dinner', 'Steak', 'Water');
INSERT INTO EXAMPLE (PERSON, MEAL, FOOD, DRINK) VALUES ('Becky', 'Lunch', 'Pizza', 'Coke');
INSERT INTO EXAMPLE (PERSON, MEAL, FOOD, DRINK) VALUES ('Becky', 'Dinner', 'Pizza', 'Milk');

当前解决方案:

SELECT t1."PERSON",
       t1."FOOD" AS "LUNCH_FOOD",
       t1."DRINK" AS "LUNCH_DRINK",
       t2."FOOD" AS "DINNER_FOOD",
       t2."DRINK" AS "DINNER_DRINK"
  FROM (SELECT *
          FROM EXAMPLE
         WHERE "MEAL" = 'Lunch') t1
       FULL JOIN (SELECT *
                    FROM EXAMPLE
                   WHERE "MEAL" = 'Dinner') t2
          ON t1."PERSON" = t2."PERSON";

编辑:应该注意我在这里使用的是完全加入,因为在实际用例中存在一个人可能在一个组中但不是另一个人的实例(即,某人可能有午餐条目但没有相应的晚餐入口)。此外,可以假设每个人只有 1 顿午餐和 1 顿晚餐,永远不会更多。

【问题讨论】:

    标签: sql oracle pivot


    【解决方案1】:

    我建议聚合:

    select name,
           max(case when meal = 'Lunch' then food end) as lunch_food,
           max(case when meal = 'Lunch' then drink end) as lunch_drink,
           max(case when meal = 'Dinner' then food end) as dinner_food,
           max(case when meal = 'Dinner' then drink end) as dinner_drink
    from example
    group by name;
    

    但是,如果您有一张大桌子,您可以将其与:

    select name, l.food, l.drink, d.food, d.drink
    from (select e.*
          from example e 
          where meal = 'Lunch'
         ) l full join
         (select e.*
          from dinner e 
          where meal = 'Dinner'
         ) d
         using (name);
    

    Oracle 具有高效的聚合机制。很难说哪个会更快,所以你应该试试你的数据。

    【讨论】:

      【解决方案2】:
      select *
      from example
      pivot (
      max(FOOD) as FOOD,max(DRINK) as DRINK
      for MEAL in ('Lunch' as Lunch,'Dinner' as Dinner)
      );
      

      结果:

      PERSON     LUNCH_FOOD LUNCH_DRINK  DINNER_FOOD  DINNER_DRINK
      ---------- ---------- ------------ ------------ ------------
      Becky      Pizza      Coke         Pizza        Milk
      Dan        Taco       Coke         Steak        Water
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多