将日期列取消透视到 Oracle 中复杂查询的单个列

Posted

技术标签:

【中文标题】将日期列取消透视到 Oracle 中复杂查询的单个列【英文标题】:Unpivot date columns to a single column of a complex query in Oracle 【发布时间】:2014-06-26 11:14:21 【问题描述】:

大家好,我遇到了一个无法解决的顽固问题。我正在尝试编制一份报告,其中来自不同表格的所有日期都需要进入报告中的单个日期字段。当然,需要将所有这些日期列中的最大或最近日期添加到报告的单个日期列中。我有多个分支/课程的多个用户将为其生成报告。

有多个博客,需要对博客标题的最新日期进行分组,即六个日期列中的 max(date_value) 应该给出该博客标题的最大或最晚日期。

预期结果:

select u.batch_uid as ext_person_key, u.user_id, cm.batch_uid as ext_crs_key,    cm.crs_id, ir.role_id as 
 insti_role, (CASE when  b.JOURNAL_IND = 'N' then 
'BLOG' else 'JOURNAL' end) as item_type, gm.title as item_name, gm.disp_title as    ITEM_DISP_NAME, be.blog_pk1 as be_blogPk1, bc.blog_entry_pk1 as bc_blog_entry_pk1,bc.pk1,

 b.ENTRY_mod_DATE as b_ENTRY_mod_DATE ,b.CMT_mod_DATE as BlogCmtModDate, be.CMT_mod_DATE as be_cmnt_mod_Date,
 b.UPDATE_DATE as BlogUpDate,  be.UPDATE_DATE as be_UPDATE_DATE,
  bc.creation_date as bc_creation_date, 

be.CREATOR_USER_ID as be_CREATOR_USER_ID ,  bc.creator_user_id as bc_creator_user_id,
b.TITLE as BlogTitle, be.TITLE as be_TITLE,
 be.DESCRIPTION as be_DESCRIPTION, bc.DESCRIPTION as bc_DESCRIPTION
FROM users u
 INNER JOIN insti_roles ir on u.insti_roles_pk1 = ir.pk1
 INNER JOIN crs_users cu ON  u.pk1 = cu.users_pk1
 INNER JOIN crs_mast cm on cu.crsmast_pk1 = cm.pk1 
 INNER JOIN blogs b on b.crsmast_pk1 = cm.pk1 
 INNER JOIN blog_entry be on b.pk1=be.blog_pk1 AND be.creator_user_id = cu.pk1 
 LEFT JOIN blog_CMT bc on be.pk1=bc.blog_entry_pk1 and bc.CREATOR_USER_ID=cu.pk1
JOIN gradeledger_mast gm ON gm.crsmast_pk1 = cm.pk1  and b.grade_handler = gm.linkId     
WHERE cu.ROLE='S' AND BE.STATUS='2' AND B.ALLOW_GRADING='Y' AND u.row_status='0'
 AND u.available_ind ='Y' and cm.row_status='0' and and      u.batch_uid='userA_157'

我得到了上述查询的结果集,其中包含我想要的多个日期列 >> 输入到单个列中。日期必须是最近的,即日期列中的最大日期。

我已经通过使用视图存储上述内容成功完成了 Unpivot 结果集并将所有日期放在一列中。但是,我 想要使用视图或表来存储结果集,然后执行 Unipivot 仅仅是因为我不能继续为每个用户创建视图 有人会查询。

日期列中的 max(date_value) 需要放在一个列中。它们如下:

* 1) b.entry_mod_date, 2) b.cmt_mod_date ,3) be.cmt_mod_date , 4) b.update_Date ,5) be.update_date, 6) bc.creation_date *

抱歉,我无法提供所有表格的说明以及 正在使用的字段。

从这些日期中获得上述最大日期的任何帮助 多个日期列合并为一列,而不使用视图或 表将不胜感激。*

【问题讨论】:

【参考方案1】:

不清楚你想要什么结果,但最简单的解决方案是使用greatest()

with t as (
      YOURQUERYHERE
     )
select t.*,
       greatest(entry_mod_date, cmt_mod_date, cmt_mod_date, update_Date,
                update_date, bc.creation_date
               ) as greatestdate
from t;

【讨论】:

我的错,我将再次编辑我的原始帖子以使要求更清晰。 感谢 Gordon 的查询,但我需要将所有放入最大的列填充到单个列中,日期与 blog_title 对齐,即该博客标题的六列中的最大日期.例如。 1) 博客 1 - 六个日期列中的某个最大日期 2) 博客 2- 六个日期列中的某个最大日期,依此类推。 然后只需使用select blogtitle 而不是select t.* 感谢您使用“greatest”的提示。我设法通过结合使用 case 语句和 union all 与日期同时使用最大来获得所需的结果集。【参考方案2】:
              select <columns>, 
                case 
                    when greatest (b_ENTRY_mod_DATE) >= greatest (BlogCmtModDate) and greatest(b_ENTRY_mod_DATE) >= greatest(BlogUpDate) 
                        then greatest( b_ENTRY_mod_DATE )
                    --<same implementation to compare each time BlogCmtModDate and BlogUpDate separately to get the greatest then 'date'> 
             ,<columns>
            FROM table
             <rest of the query>

             UNION ALL 

             Select <columns>, 
                case 
                    when greatest (be_cmnt_mod_Date) >= greatest (be_UPDATE_DATE) 
                        then greatest( be_cmnt_mod_Date )
                     when greatest (be_UPDATE_DATE) >= greatest (be_cmnt_mod_Date) 
                        then greatest( be_UPDATE_DATE )

             ,<columns>
            FROM table
             <rest of the query>

             UNION ALL

             Select <columns>, 
                GREATEST(bc_creation_date)
             ,<columns>
            FROM table
             <rest of the query>

【讨论】:

使用上面的实现我能够避免 Unpivot(因为创建视图/表并更新它对于每个用户条目来说都是昂贵的)或使 SQL 复杂(找到了一种方法来实现 Unpivot 而无需视图或表格,但性能迟缓)在单个列中获取多个日期

以上是关于将日期列取消透视到 Oracle 中复杂查询的单个列的主要内容,如果未能解决你的问题,请参考以下文章

取消透视到 Oracle 中的多个列

在 BigQuery 中的大表中取消透视日期列

Oracle 逆透视分组

Oracle 11g:取消透视多个列并包含列名

在 MySQL 中取消透视多个列

取消透视表 Oracle 中的数据