将行插入跨越2列中指定范围的现有表

时间:2019-04-02 13:36:59

标签: sql oracle

我正在尝试创建一个表,该表按组ID和每周显示促销信息。我有一张表格,显示每个组ID的促销内容以及促销持续了几周,包括开始日期和结束日期。

我想在该表中插入星期数,这样,如果促销活动持续2周,我会在两个单独的行中看到组ID,旁边的一列中有两个星期编号,并且所有其他信息都重复。

我曾尝试使用模型函数,但似乎无法弄清楚如何将其应用于数据。

我当前的表格如下:

GROUP_ID   PROMOTION_DESCRIPTION            START_DATE  END_DATE   WEEKS  START_YEARWEEK   END_YEARWEEK   MEDIA_SUPPORT
40284      Gehwol / Wartner 2e halve prijs  27-06-17    01-07-17   1      201726           201726         Radio
40315      Voordeelzakken En Dozen          26-06-17    09-07-17   2      201726           201727         Online Campagne

我希望它看起来像:

GROUP_ID   WEEK     PROMOTION_DESCRIPTION              MEDIA_SUPPORT
40284      201706   Gehwol / Wartner 2e halve prijs    Radio
40315      201726   Voordeelzakken En Dozen            Online Campagne
40315      201727   Voordeelzakken En Dozen            Online Campagne

任何帮助将不胜感激!

3 个答案:

答案 0 :(得分:0)

这可以通过生成日历并将其加入促销数据来完成。

下面的示例创建一个calendar子因子,该子因子包括2017、2018、2019年的每周(包括第53周)一条记录,然后将其promotionstart_yearweek与该日历周相交。

end_yearweek

结果:

WITH CALENDAR AS (
    SELECT (100 * YEAR_OFFSET) + WEEK_OFFSET AS CALENDAR_WEEK
    FROM (
        SELECT LEVEL AS WEEK_OFFSET
        FROM DUAL
        CONNECT BY LEVEL <= 53)
             CROSS JOIN (SELECT 2016 + LEVEL AS YEAR_OFFSET
                         FROM DUAL
                         CONNECT BY LEVEL <= 3))
SELECT GROUP_ID,
    CALENDAR_WEEK,
    PROMOTION_DESCRIPTION,
    MEDIA_SUPPORT
FROM CALENDAR
         INNER JOIN PROMOTION
ON CALENDAR_WEEK
    BETWEEN START_YEARWEEK AND END_YEAR_WEEK;

编辑:要生成ISO-Week日历,可以使用 GROUP_ID CALENDAR_WEEK PROMOTION_DESCRIPTION MEDIA_SUPPORT 40284 201726 Gehwol / Wartner 2e halve prijs Radio 40315 201726 Voordeelzakken En Dozen Online Campagne 40315 201727 Voordeelzakken En Dozen Online Campagne 3 rows selected. 中的'IW'格式掩码。

此示例日历从2014年到2022年生成ISO周:

TO_DATE

在促销示例中,它可以用作:

SELECT DISTINCT TO_NUMBER(TO_CHAR((DATE '2014-01-01' + LEVEL),'YYYYIW'))
    AS ISO_CALENDAR_WEEK FROM DUAL 
CONNECT BY (DATE '2014-01-01' + LEVEL) < DATE '2023-01-01';

结果:

WITH CALENDAR AS (
    SELECT DISTINCT TO_NUMBER(TO_CHAR((DATE '2014-01-01' + LEVEL),'YYYYIW'))
        AS ISO_CALENDAR_WEEK FROM DUAL
    CONNECT BY (DATE '2014-01-01' + LEVEL) < DATE '2023-01-01' )
SELECT GROUP_ID,
    ISO_CALENDAR_WEEK,
    PROMOTION_DESCRIPTION,
    MEDIA_SUPPORT
FROM CALENDAR
         INNER JOIN PROMOTION
ON ISO_CALENDAR_WEEK
    BETWEEN START_YEARWEEK AND END_YEAR_WEEK;

答案 1 :(得分:0)

此递归查询可以做到:

doc['endTime'].date.millis - doc['startTime'].date.millis

demo

答案 2 :(得分:0)

您可以在下面使用这种connect by level组合样式来生成更多行,具体取决于您的数据,并通过使用distinct关键字进行控制以将它们限制为一定数量。

with t( group_id, promotion_description, start_yearweek, end_yearweek, media_support ) as
(
 select 40284, 'Gehwol / Wartner 2e halve prijs', 201726, 201726, 'Radio' from dual union all
 select 40315, 'Voordeelzakken En Dozen', 201726, 201727, 'Online Campagne' from dual 
), t1 as
(
  select group_id,  
         sum(end_yearweek - start_yearweek + 1 ) as weeks
    from t
   group by group_id    
  )
  select distinct t1.group_id, start_yearweek + level - 1 as week,
         promotion_description, media_support 
   from t1
   join t on t1.group_id = t.group_id   
 connect by level <= weeks
  order by group_id, week;

 GROUP_ID   WEEK    PROMOTION_DESCRIPTION            MEDIA_SUPPORT
 --------   ------  -------------------------------  ---------------
 40284      201726  Gehwol / Wartner 2e halve prijs  Radio
 40315      201726  Voordeelzakken En Dozen          Online Campagne
 40315      201727  Voordeelzakken En Dozen          Online Campagne

P.S。无需保留可能通过查询计算出的weeks列。

Demo