这是个sybase的问题。发在oracle板块只是因为sybase区好像一个月没新帖了,问题又比较急......数据库版本:
select @@version;
SAP IQ/16.0.0.809/151113/P/sp08.39/Enterprise Linux64 - x86_64 - 2.6.18-194.el5/64bit/2015-11-13 12:24:54sybase的语法实在不清楚如何构造测试数据,甲方又不让建表。所以测试数据以oracle格式列出,请见谅。要求,使用一条查询sql完成。我有一张存有日账期的表,它们本应是连续的,但是有可能存在空挡。我需要把这些空缺的账期明细查出来。oracle的话一般会构造笛卡尔积做外关联来完成。
就像这样:with tab as (
select 'a' typ, 20180601 dt from dual union all
select 'a' typ, 20180602 dt from dual union all
select 'a' typ, 20180603 dt from dual union all
select 'b' typ, 20180601 dt from dual union all
select 'b' typ, 20180602 dt from dual union all
select 'b' typ, 20180603 dt from dual union all
select 'c' typ, 20180601 dt from dual union all
select 'c' typ, 20180603 dt from dual 
),
tab2 as (
select to_char(to_date('20180601', 'yyyymmdd') + level - 1, 'yyyymmdd') full_dt from dual connect by level <=3
),
tab3 as (
select * from tab2, (select distinct typ from tab)
),
tab4 as (
select t1.full_dt, t1.typ, t2.dt from tab3 t1, tab t2
 where t1.typ = t2.typ(+)
   and t1.full_dt = t2.dt(+)
)
select t1.full_dt, typ from tab4 t1
 where t1.dt is null
;但是我唯一找到的sybase的动态构造连续日期的方法,用于子查询会报错。
select * from (
select top 6 NUMBER(*) num,
       convert(char(10), dateadd(mm, -NUMBER(*), cast('2018/06/14' as datetime)) , 112) acct_month
  from systable
);with tab as (
select top 6 NUMBER(*) num,
       convert(char(10), dateadd(mm, -NUMBER(*), cast('2018/06/14' as datetime)) , 112) acct_month
  from systable
)
select * from tab;我的问题是要怎么构造这个笛卡尔积呢?或者用别的方法也行。真实的需求是:数据库中某个用户下存有
TABLE_A_20180601;
TABLE_A_20180602;
TABLE_B_20180601;
TABLE_A_201806;
TABLE_A_201805;
......
这样的严格命名规范的表,我要查出TABLE_A_M,TABLE_A_D,TABLE_B_D等每个逻辑表所缺失的账期的明细。(M是月表,D是日表)。统计账期区间可以写死。
写了个这样的sql,一直报错......
--3缺失账期
with tab as (
select t1.table_name, 
       reverse(substring(reverse(t1.table_name), 0, charindex('_', reverse(t1.table_name)) )) acct_month,
       reverse(substring(reverse(t1.table_name), charindex('_', reverse(t1.table_name)) + 1, 999 )) || case length(substring(reverse(t1.table_name), 0, charindex('_', reverse(t1.table_name)) )) when  6 then '_M' when 8 then '_D' else '' end logic_table,
       case length(substring(reverse(t1.table_name), 0, charindex('_', reverse(t1.table_name)) )) when  6 then 'M' when 8 then 'D' else '' end date_type
 from (
select a.table_name from systable a,sysuserperm b 
 where a.creator=b.user_id 
   and b.user_name = 'A_USER'
) t1
),
tab2 as (
select * from tab t1
 where 1 = 1
   and t1.date_type is not null
   and ((t1.date_type = 'M' and t1.acct_month > 201711 and t1.acct_month <= 201806) or (t1.date_type = 'D' and t1.acct_month > 20180401 and t1.acct_month <= 20180614))
),
table_day as (
select top 74 NUMBER(*) num,
       convert(char,cast('2018/06/15' as datetime)  - number(*),112) acct_day
  from systable
),
table_month as (
select top 6 NUMBER(*) num,
       convert(char(10), dateadd(mm, -NUMBER(*), cast('2018/06/14' as datetime)) , 112) acct_month
  from systable
),
tab3 as (
select distinct t1.logic_table, t1.date_type from tab2 t1
)
,tab4 as (
select *
  from tab3 t1, table_day t2
 where t1.date_type = 'D'
)
, tab5 as (
select t1.logic_table, t2.table_name, t1.acct_day from tab4 t1 left join tab2 t2
on (t1.logic_table || '_' || t1.acct_day = t2.table_name)
)
select * from tab5 t1
 where t1.table_name = '' or t1.table_name is null or t1.table_name = null
;日,月缺失明细分成两个sql写也行。大家有什么好方法么?