2

我有一个包含工厂列表的表(工厂 ID 和工厂名称)

Factory ID    Factory Name
1001          Factory1
1002          Factory2
1003          Factory3

用户每月将一些数据上传到每个工厂的历史表中。并且同一月份的现有工厂数据也将被不同的用户覆盖。因此历史表如下所示。

Factory ID   Month UploadedValue UploadedBy UploadedOn
1001         01    250           User1      29.11.2016 07:28 PM
1002         01    102.12        User1      29.11.2016 07:28 PM
1001         01    400           User2      30.11.2016 12.00 PM

现在,我需要为每个工厂和每个月生成一份报告,这是最新上传的(上传者和上传时间),如果没有上传,则应显示为“未上传”。这将看起来像下面的东西。

   Factory ID    Factory Name   Month   Last Upload by   Last Upload on
    1001          Factory1       01      User2            30.11.2016 12.00 PM
    1002          Factory2       01      User1            29.11.2016 07:28 PM
    1003          Factory3       01      Not Uploaded     Not Uploaded

请帮助得到这个。我尝试了分析功能。但没有运气。

4

2 回答 2

2

您可以使用该RANK()功能。假设表格是FACFAC_HIST,代码可能如下

SELECT fid, fname, month, last_uploaded_by, last_uploaded_on
  FROM ( select fh.fid fid
              , fh.fname fname
              , COALESCE(fd.month, 1) month
              , COALESCE(RANK() FIRST OVER (PARTITION BY fd.fid, fd.month 
                                                ORDER BY fd.last_uploaded_on DESC)
                         , -1) rnk
              , COALESCE(fd.uploaded_by, 'not uploaded') last_uploaded_by
              , COALESCE(fd.last_uploaded_on, 'not uploaded') last_uploaded_on
           FROM fac fh
           LEFT OUTER JOIN fac_hist fd
             ON fh.fid = fd.fid
                )
 WHERE rnk <= 1;
于 2016-11-29T14:19:48.490 回答
0

要获取每个月每个工厂的最新更新,您可以group by factory_idmonth“更新”表中选择max(updatedon)。对于其他列,您可以使用keep (dense_rank last...). 所有这些都是聚合函数(而不是分析函数)——你不会做比需要更多的工作。

查询的另一部分是数据致密化。在更新的 Oracle 版本中,这可以通过“分区外连接”来完成(谷歌阅读更多关于这个主题的信息)。我在输入数据中添加了第二个“月份”以充分说明这个概念(也请参阅输出)。注意-我没有打扰-如果确实需要,可以将所有值包装在其中以替换'Not Uploaded'为该文本,但我看不到它添加了什么。传达完全相同的信息。nullcoalesce()nullnull

with
     factories ( factory_id, factory_name ) as (
       select 1001, 'Factory1' from dual union all
       select 1002, 'Factory2' from dual union all
       select 1003, 'Factory3' from dual
     ),
     updates ( factory_id, month, uploadedvalue, uploadedby, uploadedon ) as (
       select 1001, '01', 250   , 'User1', to_date('29.11.2016 07:28 PM', 'dd.mm.yyyy hh:mi AM') from dual union all
       select 1002, '01', 102.12, 'User1', to_date('29.11.2016 07:28 PM', 'dd.mm.yyyy hh:mi AM') from dual union all
       select 1001, '01', 400   , 'User2', to_date('30.11.2016 12.00 PM', 'dd.mm.yyyy hh:mi AM') from dual
     ),
     months ( month ) as (
       select '01' from dual union all
       select '02' from dual
     )
select fm.factory_id, fm.factory_name, fm.month, s.uploadedvalue, s.uploadedby, 
       s.uploadedon
from   (
select factory_id, month, 
       min(uploadedvalue) keep (dense_rank last order by uploadedon) as uploadedvalue,
       min(uploadedby)    keep (dense_rank last order by uploadedon) as uploadedby,
       max(uploadedon) as uploadedon
from   updates
group by factory_id, month
) s
partition by (month)
right outer join (select * from factories cross join months) fm  
         on fm.factory_id = s.factory_id
        and fm.month      = s.month
order by month, factory_id
;

输出

FACTORY_ID  FACTORY_NAME  MONTH  UPLOADEDVALUE  UPLOADEDBY  UPLOADEDON
----------  ------------  -----  -------------  ----------  -------------------
1001        Factory1      01               400  User2       30.11.2016 12.00 PM
1002        Factory2      01            102.12  User1       29.11.2016 07:28 PM
1003        Factory3      01            
1001        Factory1      02            
1002        Factory2      02            
1003        Factory3      02            
于 2016-11-29T16:55:12.930 回答