【问题标题】:Summarizing redundant SQL information汇总冗余 SQL 信息
【发布时间】:2014-02-05 02:59:02
【问题描述】:

给定(Oracle 11g):

MANUFACTURER
------------
ID
NAME

CARS
---------
CAR_ID
MANUFACTURER_ID
NAME

PARTS
---------
PART_ID
CAR_ID
PART_NAME

是否可以通过 SQL 在单个查询中获取汽车和制造商的零件列表,而无需在每一行上重复冗余数据?

类似:

FORD         ESCORT         Windshield Wiper
                            Horn
                            Steering Wheel
             F-150          Windshield Wiper
                            Horn
                            Bed Liner
TOYOTA       CAMRY          Floor Mat
                            Door Handle
             CIVIC          Headlight
                            Horn

或者做这样的事情需要应用程序级逻辑和/或使用报告功能。我已经尝试了很多查询,但到目前为止没有任何结果。

【问题讨论】:

    标签: sql oracle11g group-by


    【解决方案1】:

    像这样尝试lag 函数:

    WITH manufacturer AS (
    SELECT 1 manufacturer_id, 'FORD' NAME FROM dual
    UNION ALL SELECT 2, 'TOYOTA' FROM dual)
    , CAR AS (
    SELECT 1 car_id, 1 manufacturer_id, 'ESCORT' AS name FROM dual
    UNION ALL SELECT 2, 1, 'F-150' FROM dual
    UNION ALL SELECT 3, 2, 'CAMRY' FROM dual
    UNION ALL SELECT 4, 2, 'CIVIC' FROM dual)
    , part AS (
    SELECT 1 AS part_id, 1 AS car_id, 'Windshield Wiper' AS part_name FROM dual
    UNION ALL SELECT 2, 1, 'Horn' FROM dual
    UNION ALL SELECT 3, 1, 'Steering Wheel' FROM dual
    UNION ALL SELECT 4, 2, 'Windshield Wiper' FROM dual
    UNION ALL SELECT 5, 2, 'Horn' FROM dual
    UNION ALL SELECT 6, 2, 'Bed Liner' FROM dual
    UNION ALL SELECT 7, 3, 'Floor Mat' FROM dual
    UNION ALL SELECT 8, 3, 'Door Handle' FROM dual
    UNION ALL SELECT 9, 4, 'Headlight' FROM dual
    UNION ALL SELECT 10, 4, 'Horn' FROM dual)
    SELECT case lag (m.name) over (order by p.part_id)
                when m.name then null
                else m.name
           end as manufcturer,
           case lag (c.name) over (order by p.part_id)
                when c.name then null
                else c.name
           end as carname,
           p.part_name
      FROM manufacturer m INNER JOIN car c ON m.manufacturer_id = c.manufacturer_id
            INNER JOIN part p ON p.car_id = c.car_ID
    ;
    

    输出:

    MANUFACTURER  CARNAME   PART_NAME
    ------------- --------- -----------------
    FORD          ESCORT    Windshield Wiper
                            Horn
                            Steering Wheel
                  F-150     Windshield Wiper
                            Horn
                            Bed Liner
    TOYOTA        CAMRY     Floor Mat
                            Door Handle
                  CIVIC     Headlight
                            Horn
    

    【讨论】:

      【解决方案2】:

      得到结果的自然方法是:

      select m.name as manufacturer_name, c.name as car_name, p.name as part_name
      from manufacturer m join
           cars c
           on c.manufacturer_id = m.id join
           parts p
           on p.car_id = c.car_id;
      

      这将采用表格中所有单元格都填充的格式(因此'Ford' 将位于表格的前几行)。

      如果你只想每个名字的第一个出现,你可以使用row_number()(并且一定要把结果排在最后):

      select (case when m_seqnum = 1 then manufacturer_name else '' end) as manufacturer_name,
             (case when c_seqnum = 1 then car_name else '' end) as car_name,
             part_name
      from (select m.name as manufacturer_name, c.name as car_name, p.name as part_name,
                   row_number() over (partition by m.name order by c.name, p.name) as m_seqnum,
                   row_number() over (partition by m.name, c.name order by p.name) as c_seqnum
            from manufacturer m join
                 cars c
                 on c.manufacturer_id = m.id join
                 parts p
                 on p.car_id = c.car_id
           ) mcp
      order by manufacturer_name, car_name, part_name;
      

      【讨论】:

      • +1 善用row_number()和第一次查询的澄清。
      猜你喜欢
      • 1970-01-01
      • 2020-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-12
      • 2021-03-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多