从Oracle表中选择上载历史记录

时间:2016-11-29 14:07:57

标签: sql oracle window-functions dense-rank partition-by

我有一个表包含工厂列表(工厂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

请帮忙解决这个问题。我尝试过分析功能。但没有运气。

2 个答案:

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

答案 1 :(得分:0)

要仅获取每个月每个工厂的最新更新,您可以在“更新”表格中monthmax(updatedon),然后选择keep (dense_rank last...)。对于其他列,您可以使用'Not Uploaded'。所有这些都是聚合函数(而不是分析函数) - 并且您不需要做更多的工作。

查询的另一部分是数据密集化。在更新版本的Oracle中,可以使用“分区外连接”(Google阅读有关此主题的更多信息)来完成此操作。我在输入数据中添加了第二个“月”以充分说明概念(请参阅输出)。注意 - 我没有使用null代替coalesce() - 如果真的需要,可以将null中的所有值换行以用该文本替换null,但我不知道看看它增加了什么。 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            

<强>输出

=IIF(SUM(Fields!VT.Value)=0,"0:00",
 IIF(SUM(Fields!VT.Value)< 0,"-"&Format(DateAdd("s",ABS(SUM(Fields!VT.Value)), "00:00"), "HH:mm"),
 Format(DateAdd("s",ABS(SUM(Fields!VT.Value)), "00:00"), "HH:mm")))