Oracle SQL-基于记录的日期与历史记录的标记记录

时间:2016-07-04 11:13:01

标签: sql oracle

这是我在论坛上的第一篇文章。通常我能够找到我需要的东西 - 但说实话 - 我不确定如何向这个问题提出正确的问题。因此,如果论坛上已经有答案而我错过了,请接受我的道歉。

我通过Benthic Software在Oracle数据库中运行以下代码:

SELECT
T1."REGION"
, T1."COUNTRY"
, T1."IDNum"
, T1."CUSTOMER"
, T1."BUSSINESS"
, T3."FISCALYEARMONTH"
, T3."FISCALYEAR"
, SUM(T4."VALUE") 
,"HISTORICAL_PURCHASE_FLAG"

FROM
"DATABASE"."SALES" T4
, "DATABASE"."CUSTOMER" T1
, "DATABASE"."PRODUCT" T2
, "DATABASE"."TIME" T3

WHERE
T4."CUSTOMERID" = T1."CUSTOMERID"
AND T4."PRODUCTID" = T2."PRODUCTID"
AND T4."DATEID" = T3."DATEID"
AND T3."FISCALYEAR" IN ('2016')
AND T1."COUNTRY" IN ('ENGLAND', 'France')


GROUP BY
T1."REGION"
, T1."COUNTRY"
, T1."IDNum"
, T1."CUSTOMER"
, T1."BUSSINESS"
, T3."FISCALYEARMONTH"
, T3."FISCALYEAR"
;

此查询向我提供有关交易的信息。如您所见,我想添加一个名为“HISTORICAL_PURCHASE_FLAG”的列。

我希望查询采用CUSTOMER和FISCALYEARMONTH。然后,我想检查是否有任何为CUSTOMER注册的交易,过去最多2年。

所以我想说得到以下结果:

LineNum REGION  COUNTRY IDNum   CUSTOMER            BUSSINESS       FISCALYEARMONTH FISCALYEAR  VALUE      HISTORICAL_PURCHASE_FLAG
1       Europe  ENGLAND 255     Abraxo Cleaner Co.  Chemicals       201605           2016       34,567.00   
2       Europe  FRANCE  123     Metal Trade          Heavy          201602           2016       12,500.00   
3       Europe  ENGLAND 255     Abraxo Cleaner Co.  Chemicals       201601           2016       8,400.00    

LineNum 1显示了在201605注册的Abraxo Cleaner Co.的交易。而LineNum 3也适用于Abraxo Cleaner Co.但在201601注册。我需要查询的是将LineNum 1标记为“现有”。因为之前的交易已经注册。

另一方面,LineNum 3是第一次为Abraxo Cleaner Co.注册交易,因此该行将被标记为“新”。

总而言之,我希望对每行数据进行单独处理。并检查CUSTOMER&是否有任何先前的数据记录。 FISCALYEARMONTH - 24个月。

提前感谢您的帮助。

4 个答案:

答案 0 :(得分:0)

您可以使用LAG功能:

SELECT
"REGION"
, "COUNTRY"
, "IDNum"
, "CUSTOMER"
, "BUSSINESS"
, "FISCALYEARMONTH"
, "FISCALYEAR"
, SUM("VALUE") 
, MAX(CASE WHEN to_date(prev_fym,'YYYYMM')  >= ADD_MONTHS (to_date("FISCALYEARMONTH",'YYYYMM'), -24) THEN 'Existing' 
           ELSE NULL END) "HISTORICAL_PURCHASE_FLAG"
FROM
(
    SELECT
    T1."REGION"
    , T1."COUNTRY"
    , T1."IDNum"
    , T1."CUSTOMER"
    , T1."BUSSINESS"
    , T3."FISCALYEARMONTH"
    , T3."FISCALYEAR"
    , T4."VALUE"
    , LAG ("FISCALYEARMONTH", 1) OVER (PARTITION BY T1."IDNum" ORDER BY T3."FISCALYEARMONTH" DESC) prev_fym 
    FROM
    "DATABASE"."SALES" T4
    , "DATABASE"."CUSTOMER" T1
    , "DATABASE"."PRODUCT" T2
    , "DATABASE"."TIME" T3
    WHERE
    T4."CUSTOMERID" = T1."CUSTOMERID"
    AND T4."PRODUCTID" = T2."PRODUCTID"
    AND T4."DATEID" = T3."DATEID"
    AND T1."COUNTRY" IN ('ENGLAND', 'France')
    AND T3."FISCALYEAR" IN ('2014','2015','2016')
)
WHERE "FISCALYEAR" IN ('2016')
GROUP BY
"REGION"
, "COUNTRY"
, "IDNum"
, "CUSTOMER"
, "BUSSINESS"
, "FISCALYEARMONTH"
, "FISCALYEAR"
;

答案 1 :(得分:0)

使用简化的"输入" table ...您可以使用LAG()分析函数和比较条件来填充最后一列。我假设你的fiscalyearmonth是一个数字 - 如果是一个字符字段,请在fiscalyearmonth中包裹TO_NUMBER()。 (如果事实上你将它们存储为真正的Oracle日期,可能date 2016-06-01而不是201606,那会好得多,但我使用的是你现在所拥有的...并利用数字格式, " 24个月前"简单地表示"减去200")。

with inputs (linenum, idnum, fiscalyearmonth) as (
       select 1, 255, 201605 from dual union all
       select 2, 123, 201602 from dual union all
       select 3, 255, 201601 from dual union all
       select 4, 255, 201210 from dual
     )
select linenum, idnum, fiscalyearmonth, 
       case when fiscalyearmonth 
                 - lag(fiscalyearmonth) 
                           over (partition by idnum order by fiscalyearmonth) < 200
            then 'Existing' else 'New' end         as flag
from   inputs
order by linenum;


   LINENUM      IDNUM FISCALYEARMONTH FLAG
---------- ---------- --------------- --------
         1        255          201605 Existing
         2        123          201602 New
         3        255          201601 New
         4        255          201210 New

答案 2 :(得分:0)

另一种解决方案可能是外部加入&#34; DATABASE&#34;。&#34; SALES&#34; T4第二次作为T5,通过WHERE兑换会计年度&lt; t4.FiscalYear-2。如果Column为NULL,则记录为new,如果外连接产生值,则记录为历史记录。

答案 3 :(得分:0)

你可以使用如下的row_number()函数...根据你的需要修改...我假设2年(意味着从sysdate开始的前24个月)。 您可以单独运行子查询以检查其工作方式。

Select 
"REGION"
,"COUNTRY"
,"IDNum"
,"CUSTOMER"
,"BUSSINESS"
,"FISCALYEARMONTH"
,"FISCALYEAR"
,"VALUE"
, ( case when ( TXNNO = 1 or TOTAL_TXN_LAST24MTH = 0 ) then 'New' else 'Existing' end ) as "HISTORICAL_PURCHASE_FLAG"  -- if no txn in last 24 month or its first txn then 'new' else 'existing'
from
(
  select 
  SubQry."REGION"
  , SubQry."COUNTRY"
  , SubQry."IDNum"
  , SubQry."CUSTOMER"
  , SubQry."BUSSINESS"
  , SubQry."FISCALYEARMONTH"
  , SUBQRY."FISCALYEAR"
  , SUBQRY."VALUE"
  , ROW_NUMBER() over (partition by SUBQRY."REGION",SUBQRY."COUNTRY",SUBQRY."IDNum",SUBQRY."CUSTOMER",SUBQRY."BUSSINESS" order by SUBQRY."FISCALYEARMONTH") as TXNNO,
  , SUM(case when (TO_NUMBER(TO_CHAR(sysdate,'YYYYMM')) - SUBQRY."FISCALYEARMONTH") < 24 then 1 else 0 end) as TOTAL_TXN_LAST24MTH
  From
  (
    SELECT
    T1."REGION"
    , T1."COUNTRY"
    , T1."IDNum"
    , T1."CUSTOMER"
    , T1."BUSSINESS"
    , T3."FISCALYEARMONTH"
    , T3."FISCALYEAR"
    , SUM(T4."VALUE") as VALUE
    FROM
    "DATABASE"."SALES" T4
    , "DATABASE"."CUSTOMER" T1
    , "DATABASE"."PRODUCT" T2
    , "DATABASE"."TIME" T3
    WHERE
    T4."CUSTOMERID" = T1."CUSTOMERID"
    AND T4."PRODUCTID" = T2."PRODUCTID"
    AND T4."DATEID" = T3."DATEID"
    AND T3."FISCALYEAR" IN ('2016')
    AND T1."COUNTRY" IN ('ENGLAND', 'France')
    GROUP BY
    T1."REGION"
    , T1."COUNTRY"
    , T1."IDNum"
    , T1."CUSTOMER"
    , T1."BUSSINESS"
    , T3."FISCALYEARMONTH"
    , T3."FISCALYEAR"
  ) SUBQRY
);