总结冗余的SQL信息

时间:2014-02-05 02:59:03

标签: sql oracle11g group-by

鉴于(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

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

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

获得结果的自然方式是:

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;