带案例的条件上传

时间:2014-10-22 14:11:24

标签: sql sql-server ssis

从旧系统进行数据迁移后,我遇到了没有日期记录的情况。

eg.1

eg.2

我上面给出的例子是我的情况。我无处可从那些NULL中获取数据。那么逻辑上设置为:

  1. 获取该范围内的次要日期(00013或00021)。
  2. 使用系列的最早日期更新记录。
  3. 我想你做了一个CASE来实现这个目标。有人可以帮我找一个方法来获得它吗?

3 个答案:

答案 0 :(得分:5)

我设置了一个小POC来向您展示如何做到这一点。

CREATE TABLE
    #T
(
    c1 char(9) NOT NULL
,   c2 datetime NULL
);

INSERT INTO
    #T
(
    c1
,   c2
)
VALUES
    ('0011.001', '2008-12-16T00:00:00.000')
,   ('0013.000', NULL)
,   ('0013.001', '2008-07-10T00:00:00.000')
,   ('0013.002', NULL)
,   ('9999.000', '2009-07-03T00:00:00.000');

此时,我们有一张桌子,上面有3个独特的"乐队"这就是我在该专栏中调用前4个字符的原因。这不是一个数字,因为数字没有前导零。那是演示文稿。

-- Identify the minimum value per first 4 digit values
SELECT
    LEFT(T.c1, 4) AS Band
,   MIN(T.c2) AS MinDate
FROM
    #T AS T
GROUP BY
    LEFT(T.c1, 4)

运行该查询会将结果显示为

Band    MinDate
0011    2008-12-16 00:00:00.000
0013    2008-07-10 00:00:00.000
9999    2009-07-03 00:00:00.000

这就是我的期望。现在我只需要使用这些值来回填我错过的日期。

-- Use this query to backfill data
-- the join condition here makes things painful for large data sets


UPDATE
    T
SET
    T.c2 = D.MinDate
FROM
    #T AS T
    -- use the above query as a derived table
    INNER JOIN
    (
        -- Identify the minimum value per first 4 digit values
        SELECT
            LEFT(T.c1, 4) AS Band
        ,   MIN(T.c2) AS MinDate
        FROM
            #T AS T
        GROUP BY
            LEFT(T.c1, 4)
    ) D
    ON D.Band = LEFT(T.c1, 4)
WHERE
    T.c2 IS NULL;

当然,如果你使用的是SQL Server 2005+(现在很可能),你可以避免在窗口MIN()的帮助下使用连接:

UPDATE
    T
SET
    T.c2 = T.MinDate
FROM
    (
        SELECT
            T.c2
        ,   MIN(T.c2) OVER (PARTITION BY LEFT(T.c1, 4)) AS MinDate
        FROM
            #T AS T
    ) T
WHERE
    T.c2 IS NULL;

基本上,除了c2值之外,上述工作方式与前面的解决方案相同,并且它们的相应最小值在同一子查询中计算并返回,子查询用作派生表(在此上下文中可更新)。

答案 1 :(得分:2)

首先:将此移动到新数据库是件好事。在一列中包含范围和子范围是一种糟糕的设计。

这应该做:

update mytable
set mydate = 
(
  select min(mydate)
  from mytable other
  where left(other.range,5) = left(mytable.range,5)
)
where mydate is null;

答案 2 :(得分:1)

这是一个应该做你想要的查询。它假定您的源数据表名为 YourData ,相关列名为 Range Date

如果修复此问题是一次性任务,则可以从SSMS运行此查询;如果需要将修复作为重复过程的一部分,则可以使用SSIS的执行SQL任务

UPDATE YourData
SET Date = MinDate
FROM (
    -- get the minimum date inside a Band
    SELECT Band, MinDate = MIN(Date)
    FROM (
        -- split Range at the period, putting everything before the period into Band
        SELECT Band = LEFT(Range, CHARINDEX('.', Range, 0) - 1), 
            Date
        FROM YourData
    ) AS Data
    GROUP BY Band
) AS DateData
WHERE Date IS NULL
    AND DateData.Band = LEFT(Range, CHARINDEX('.', Range, 0) - 1)