从旧系统进行数据迁移后,我遇到了没有日期记录的情况。
我上面给出的例子是我的情况。我无处可从那些NULL中获取数据。那么逻辑上设置为:
我想你做了一个CASE来实现这个目标。有人可以帮我找一个方法来获得它吗?
答案 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)