如何按不同列对两个表进行分组?

时间:2014-04-12 08:08:43

标签: sql oracle

我有一张带有驾照号码和旅行日期的旅行表。除此之外,我还有许可证表,即许可证号码和驱动程序名称。我想创建一份报告,其中包括司机的全名以及每年的平均出行次数。考虑1995年,1996年和1997年。这变得如此复杂:

要按行程表中的年份对记录进行分组,我这样做了很好:

 SELECT  TO_CHAR(TRIP_DATE, 'YYYY') AS year,   count(1) trips
    FROM TRIP tr  join driver d on (d.l# = tr.l#)
            join employee e on (e.e# = d.e#)
    GROUP BY TO_CHAR(TRIP_DATE, 'YYYY');

输出:

YEAR      TRIPS
---- ----------
1997          7
1995         12
1996         13
1999          2
1998          1

但是,当我想添加第二个表并再次按每个驱动程序对它们进行分组时,它无法正常工作:

 SELECT  TO_CHAR(TRIP_DATE, 'YYYY') AS year, e.fname, e.lname ,   count(1) trips
    FROM TRIP tr  join driver d on (d.l# = tr.l#)
    join employee e on (e.e# = d.e#)
    GROUP BY TO_CHAR(TRIP_DATE, 'YYYY'),e.fname, e.lname;

正如你在这里看到的,我有三张桌子。许可证号码是带有全名的emplyee的外键。

输出:

YEAR FNAME
---- --------------------------------------------------
LNAME                                                   TRIPS
-------------------------------------------------- ----------
1997 John
Lucas                                                       2

1999 Adam
Taylor                                                      1

1995 John
Doe                                                         2

预期产出:

YEAR      TRIPS
---- ----------
1997          7   
    john avg=3.2;
    mat  avg=4.2;
1995         12
    john avg=3.2;
    mat  avg=4.2;

1996         13
    john avg=3.2;
    mat  avg=4.2;

1999          2
    john avg=3.2;
    mat  avg=4.2;

1998          1
    john avg=3.2;
    mat  avg=4.2;

2 个答案:

答案 0 :(得分:2)

我的十进制数有问题,所以我没有完全测试AVG,我为你做了2次查询,试试看。

使用AVG功能

SELECT
   TotalTripsByYear.year
   ,TotalTripsByYear.trips as totalTripsOfYear
   ,fullname
   ,avg_trips as avgTripsOfDriverByYear

FROM 
   (SELECT  
       TO_CHAR(TRIP_DATE, 'YYYY') AS year
       ,count(*) trips
    FROM 
       TRIP tr  
       join driver d 
           on (d.l# = tr.l#)
       join employee e 
           on (e.e# = d.e#)
    GROUP BY TO_CHAR(TRIP_DATE, 'YYYY')) TotalTripsByYear

   left join (SELECT 
                 year
                 ,e.fname ||' ' || e.lname as fullname
                 ,AVG(trips) as avg_trips
              FROM 
                 (SELECT  
                      TO_CHAR(TRIP_DATE, 'YYYY') AS year
                      ,d.e#
                      ,count(*) trips
                  FROM 
                      TRIP tr  
                      join driver d 
                        on (d.l# = tr.l#)
                  GROUP BY 
                      TO_CHAR(TRIP_DATE, 'YYYY')
                      ,d.e#) TotalTripsByDriversByYear
              INNER JOIN employee e
              on TotalTripsByDriversByYear.e# = e.e#
          GROUP BY 
              year
              ,e.fname||' ' || e.lname) AvgTripsByDriversByYear
        on AvgTripsByDriversByYear.year = TotalTripsByYear.year

进行手动AVG

SELECT
    TotalTripsByYear.year
    ,TotalTripsByYear.trips as totalTripsOfYear
    ,fullname
    ,avg_trips as avgTripsOfDriverByYear

FROM 
    (SELECT  
        TO_CHAR(TRIP_DATE, 'YYYY') AS year
        ,count(*) trips
     FROM TRIP tr  
        join driver d 
            on (d.l# = tr.l#)
        join employee e 
            on (e.e# = d.e#)
     GROUP BY 
        TO_CHAR(TRIP_DATE, 'YYYY')) TotalTripsByYear

    left join (SELECT 
                  TotalTripsByDriversByYear.year
                  ,e.fname ||' ' || e.lname as fullname
                  ,TotalTripsByDriversByYear.trips / totalTripsByYear.total as avg_trips
               FROM 
                  (SELECT  
                      TO_CHAR(TRIP_DATE, 'YYYY') AS year
                      ,d.e#
                      ,count(*) trips
                   FROM 
                      TRIP tr  
                      join driver d on (d.l# = tr.l#)
                   GROUP BY 
                      TO_CHAR(TRIP_DATE, 'YYYY')
                      , d.e#) TotalTripsByDriversByYear
                  INNER JOIN (SELECT 
                                  TO_CHAR(TRIP_DATE, 'YYYY') as year
                                  , COUNT(*) as total 
                              FROM TRIP 
                              GROUP BY TO_CHAR(TRIP_DATE, 'YYYY')) as totalTripsByYear
                      on TotalTripsByDriversByYear.year = totalTripsByYear.year
                  INNER JOIN employee e
                  on TotalTripsByDriversByYear.e# = e.e#
              ) AvgTripsByDriversByYear
        on AvgTripsByDriversByYear.year = TotalTripsByYear.year

答案 1 :(得分:1)

SELECT  TO_CHAR(TRIP_DATE, 'YYYY') AS year, e.fname||' ' || e.lname ,   count(1) trips
    FROM TRIP tr  join driver d on (d.l# = tr.l#)
    join employee e on (e.e# = d.e#)
    GROUP BY TO_CHAR(TRIP_DATE, 'YYYY'),e.fname||' ' || e.lname;