首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >MS :用较少的变量将SCD-2转换为SCD-2

MS :用较少的变量将SCD-2转换为SCD-2
EN

Stack Overflow用户
提问于 2020-10-07 13:45:06
回答 2查看 255关注 0票数 0

我从包含许多参数的SCD-2表中检索数据,我需要只使用其中一个参数来构建自己的SCD-2。因此,我需要摆脱过多的间隔。请推荐一种算法来以最好的方式执行该操作。

我从源表中收到的信息:

我需要把它转换成:

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-10-08 10:39:06

您可以使用以下步骤获得所需的结果。当然,您可以使用子选择或CTE在一步内完成这一切,但是为了更好地跟踪,我预先设置了临时表。

代码语言:javascript
运行
复制
DROP TABLE IF EXISTS #source;
CREATE TABLE #source (key1 integer, value1 integer, row_actual_from date, row_actual_to date);
 
INSERT INTO #source
VALUES
(19999923, 15,   '2020-01-01', '2020-01-02'),
(19999923, 15,   '2020-01-03', '2020-01-05'),
(19999923, 15,   '2020-01-06', '2020-01-08'),
(19999923, 11,   '2020-01-09', '2020-01-12'),
(19999923, 3434, '2020-01-13', '2020-01-15'),
(19999923, 11,   '2020-01-16', '2020-01-20'),
(19999923, 15,   '2020-01-21', '2020-02-02'),
(19999923, 3434, '2020-02-03', '2020-02-10'),
(19999923, 3434, '2020-02-11', '2020-02-19'),
(19999923, 3434, '2020-02-20', '2020-02-25'),
(19999923, 99,   '2020-02-26', '9999-12-31');

步骤1:确定单个值期间的开始和结束。

注意,在延迟/引导中,必须有一个值作为空替换(例如-99),这个值与列中的可能值不匹配。

代码语言:javascript
运行
复制
    DROP TABLE IF EXISTS #step1;
    SELECT
        key1, value1, row_actual_from, row_actual_to
        , period_start = CASE WHEN LAG(value1,  1, -99) OVER (PARTITION BY key1 ORDER BY row_actual_from) <> value1 THEN 1 ELSE 0 END
        , period_end   = CASE WHEN LEAD(value1, 1, -99) OVER (PARTITION BY key1 ORDER BY row_actual_from) <> value1 THEN 1 ELSE 0 END
    INTO #step1
    FROM #source
    ORDER BY key1, row_actual_from;

步骤2:对开始/结束行进行筛选,并将end的row_actual_to分配给start。

如果值的周期只有一行,则该行的period_start和period_end设置为1,因此和值为2。在这种情况下,row_acutal_to的内容已经达到了希望的值。

代码语言:javascript
运行
复制
    DROP TABLE IF EXISTS #step2;
    SELECT
        key1, value1, row_actual_from, row_actual_to, period_start, period_end
      , valid_from = row_actual_from
      , valid_to   = CASE (period_start + period_end)
                     WHEN 1 THEN LEAD(row_actual_to, 1) OVER (PARTITION BY key1, value1 ORDER BY row_actual_from)
                     WHEN 2 THEN row_actual_to ELSE NULL END
    INTO #step2
    FROM #step1
    WHERE (period_start + period_end) > 0
    ORDER BY key1, row_actual_from;

步骤3:筛选(调整)值周期的开始行。

代码语言:javascript
运行
复制
    SELECT key1, value1, valid_from, valid_to
    FROM   #step2
    WHERE  period_start = 1
    ORDER BY key1, row_actual_from;
票数 3
EN

Stack Overflow用户

发布于 2020-10-07 17:21:52

这显然是复杂的,因为相同的“值”可以在多个组中重复,所以您不能只使用简单的MIN/MAX函数。您可能可以在javascript存储的proc中对其进行编码,但我想我会尝试在(几乎)纯SQL中找到解决方案。

挑战是,每当值发生变化时,尝试创建一个“组”--就像您可以在组内的日期上做一个简单的MIN/MAX一样。我的方式(希望!)解决这个问题的办法如下:

  1. 创建CTE,当当前行的值与上一行的值不同时,计算出的字段设置为序列中的下一个值;如果没有差异,则该字段设置为null这是很重要的,因为下一个CTE处理nulls
  2. 中的滞后函数创建了第二个CTE,其中计算出的分组列在上一列中创建的计算列中被设置为最后一个非空值--使用L滞后函数集来忽略第二个CTE中的
  3. ,查询按键、值和分组列

分组的min和max日期值。

代码语言:javascript
运行
复制
CREATE TABLE SRC_TABLE (key1 integer, value1 integer, row_actual_from date, row_actual_to date);

INSERT INTO SRC_TABLE
VALUES
(19999923, 15, '2020-01-01', '2020-01-02'),
(19999923, 15, '2020-01-03', '2020-01-05'),
(19999923, 15, '2020-01-06', '2020-01-08'),
(19999923, 3434, '2020-01-09', '2020-01-12'),
(19999923, 3434, '2020-01-13', '2020-01-15'),
(19999923, 15, '2020-01-16', '2020-01-20'),
(19999923, 15, '2020-01-21', '9999-12-31');


create or replace sequence seq_01 start = 1 increment = 1;
WITH T1 AS (
  SELECT KEY1, VALUE1, row_actual_from, row_actual_to
  ,CASE WHEN LAG(VALUE1,1,0) OVER (PARTITION BY KEY1 ORDER BY row_actual_from ASC) = VALUE1 THEN null ELSE seq_01.nextval END AS CHK_MIN
  from SRC_TABLE
  order by row_actual_from
),
T2 AS (
  SELECT KEY1, VALUE1, row_actual_from, row_actual_to, CHK_MIN
  ,CASE WHEN CHK_MIN IS NULL THEN LAG(CHK_MIN,1,0) IGNORE NULLS OVER (PARTITION BY KEY1 ORDER BY row_actual_from ASC) ELSE CHK_MIN END AS CHK_MIN_GRP
  FROM T1
)
SELECT KEY1, VALUE1, MIN(ROW_ACTUAL_FROM), MAX(ROW_ACTUAL_TO)
FROM T2
GROUP BY KEY1, VALUE1, CHK_MIN_GRP
;

结果

代码语言:javascript
运行
复制
KEY1        VALUE1      MIN(ROW_ACTUAL_FROM)    MAX(ROW_ACTUAL_TO)
19999923        15      2020-01-01              2020-01-08
19999923        3434    2020-01-09              2020-01-15
19999923        15      2020-01-16              9999-12-31
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64245385

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档