Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 如何使用最近的可用值(SQL Server)填充空值_Sql Server - Fatal编程技术网

Sql server 如何使用最近的可用值(SQL Server)填充空值

Sql server 如何使用最近的可用值(SQL Server)填充空值,sql-server,Sql Server,我使用的是SQL Server,我有一个如下表: CREATE TABLE #Test ( ID varchar(9), [year] varchar(7), Code varchar(9) ) INSERT INTO #test (ID, [year], code) VALUES ('8479', '2006', 'A'), ('8479', '2007', 'A'), ('8479', '2008', 'A'), ('8479', '2009', NU

我使用的是SQL Server,我有一个如下表:

CREATE TABLE #Test
(
    ID varchar(9),
    [year] varchar(7),
    Code varchar(9)
)

INSERT INTO #test (ID, [year], code)
VALUES ('8479', '2006', 'A'), ('8479', '2007', 'A'),
       ('8479', '2008', 'A'), ('8479', '2009', NULL),
       ('8479', '2010', NULL), ('8479', '2011_H1', NULL),
       ('8479', '2011_H2', NULL), ('8479', '2012_H1', 'B'),
       ('8479', '2012_H2', 'B'), ('8479', '2013_H1', 'B'),
       ('8479', '2013_H2', 'B'),
       ('5477', '2008', 'Z'), ('5477', '2009', 'Z'),
       ('5477', '2010', 'Z'), ('5477', '2011_H1', NULL),
       ('5477', '2011_H2', 'R')
我想用最接近的值填充空代码值,该值可用于按年份顺序和任何方向最接近的特定ID。如果NULL与值之间的距离相等,则应优先考虑下一年

因此,我希望这个结果是:

ID      year   Code
-------------------
8479    2006    A
8479    2007    A
8479    2008    A
8479    2009    A
8479    2010    A
8479    2011_H1 B
8479    2011_H2 B
8479    2012_H1 B
8479    2012_H2 B
8479    2013_H1 B
8479    2013_H2 B
5477    2008    Z
5477    2009    Z
5477    2010    Z
5477    2011_H1 R
5477    2011_H2 R
有些年份被分成两部分——H1之后是H2

每个ID的空条目数将有所不同

我甚至尝试了以下几点:

Update #test
set Code = (select top 1 b.Code 
            from #Test b
            where LEFT(#test.[year],4) > LEFT(b.[year],4) 
            and #test.ID = b.ID
            and b.Code IS NOT NULL)
Where Code IS NULL
但这显然行不通,突出了我面临的两个主要问题:

我可以做些什么来为带有H1和H2后缀的“年份”条目分配订单

我该如何整合那些无论方向如何都能找到最近值的功能


我对这方面还不太熟悉,所以非常感谢您的帮助。我应该补充一点,我继承了这个数据库,目前我还不能对这个结构做任何根本性的改变——我意识到如果我的年数被存储为日期,那么我就成功了一半!谢谢。

试试这样的。这是一个非常慢的方法,但是如果你只需要做一次,它就应该做

UPDATE #test
    SET
        #test.code = (
            SELECT
                TOP(1)
                    ts.code
                FROM #test ts
                WHERE #test.ID = ts.ID
                    AND ts.code IS NOT NULL
                ORDER BY Abs(Cast(Left(#test.[year], 4) as smallint) - Cast(Left(ts.[year], 4) as smallint))
            )
    WHERE #test.code IS NULL

试试这样的。这是一个非常慢的方法,但是如果你只需要做一次,它就应该做

UPDATE #test
    SET
        #test.code = (
            SELECT
                TOP(1)
                    ts.code
                FROM #test ts
                WHERE #test.ID = ts.ID
                    AND ts.code IS NOT NULL
                ORDER BY Abs(Cast(Left(#test.[year], 4) as smallint) - Cast(Left(ts.[year], 4) as smallint))
            )
    WHERE #test.code IS NULL
试试这个

; WITH test_data as
(
    SELECT ID, [year], [Code], rn = row_number() OVER (PARTITION BY ID ORDER BY [year])
    FROM    #Test
)
UPDATE  t
SET Code    = c.Code
FROM    test_data t
    CROSS APPLY
    (
        SELECT  TOP 1 x.Code
        FROM    test_data x
        WHERE   x.ID    = t.ID
        AND x.Code  is not null
        ORDER BY ABS(t.rn - x.rn)
    ) c
WHERE   t.Code  IS NULL
试试这个

; WITH test_data as
(
    SELECT ID, [year], [Code], rn = row_number() OVER (PARTITION BY ID ORDER BY [year])
    FROM    #Test
)
UPDATE  t
SET Code    = c.Code
FROM    test_data t
    CROSS APPLY
    (
        SELECT  TOP 1 x.Code
        FROM    test_data x
        WHERE   x.ID    = t.ID
        AND x.Code  is not null
        ORDER BY ABS(t.rn - x.rn)
    ) c
WHERE   t.Code  IS NULL
下面的代码将代码设置为所需的代码,在子查询中从具有相似ID的记录中选择,代码不为null非常重要,按年份差异排序差异越小越好,相似的记录按年份递减排序,以便在出现相似差异时选择较新的年份。此更新针对具有空代码的每条记录执行:

但是,这是有问题的,因为在给定ID只有空代码值的情况下,结果也将为空。让我们假设对于这种情况我们有一个“默认”代码。然后,您可以执行以下操作:

update #Test
set Code = ifnull((select top(1) t.Code
            from #Test t
            where t.ID = #Test.ID and not (t.Code is null)
            ORDER BY Abs(Cast(Left(#test.year, 4) as smallint) - Cast(Left(t.year, 4) as smallint)), t.year desc), 'default')
where Code is null
下面的代码将代码设置为所需的代码,在子查询中从具有相似ID的记录中选择,代码不为null非常重要,按年份差异排序差异越小越好,相似的记录按年份递减排序,以便在出现相似差异时选择较新的年份。此更新针对具有空代码的每条记录执行:

但是,这是有问题的,因为在给定ID只有空代码值的情况下,结果也将为空。让我们假设对于这种情况我们有一个“默认”代码。然后,您可以执行以下操作:

update #Test
set Code = ifnull((select top(1) t.Code
            from #Test t
            where t.ID = #Test.ID and not (t.Code is null)
            ORDER BY Abs(Cast(Left(#test.year, 4) as smallint) - Cast(Left(t.year, 4) as smallint)), t.year desc), 'default')
where Code is null


您是希望实时填充它们,还是希望通过更新再次填充它们为什么要将一年存储为varchar?如果要添加季度,请首先使用附加列或datetime/date。你的方法缓慢、复杂且容易出错。后者是使用更新。嗨,蒂姆,谢谢你的评论。由于varchar不是我设计的,我只是想知道我是否能以目前的形式解决这个问题。如果没有,那么我将按照您的建议使用一个额外的列。您是希望实时填充它们,还是作为第二次更新来填充它们为什么将一年存储为varchar?如果要添加季度,请首先使用附加列或datetime/date。你的方法缓慢、复杂且容易出错。后者是使用更新。嗨,蒂姆,谢谢你的评论。由于varchar不是我设计的,我只是想知道我是否能以目前的形式解决这个问题。如果不是,那么我将按照您的建议使用一个附加列。子查询应该检查代码是否不为NULL?您应该返回代码而不是年份?子查询应该检查代码是否不为空?您应该返回代码而不是年份?您确定这会起作用吗?我认为CROSS APPLY中的列表需要为每个更新的行提供一行,更精确地说,每插入一次值。这只供应一个。是的。它起作用了。在这种情况下,交叉应用的工作方式与子查询的工作方式相同。您确定这会工作吗?我认为CROSS APPLY中的列表需要为每个更新的行提供一行,更精确地说,每插入一次值。这只供应一个。是的。它起作用了。交叉应用在本例中的工作方式与您的子查询tanks Lajos相同,这几乎是我所需要的,对于我当前的目的来说已经足够接近了。唯一轻微的问题是,通过按年份递减排序来优先考虑较新的年份,这也可以扭转上半年和下半年的顺序。如果可以避免,那么这将是一个完美的解决方案。在这种情况下,这似乎是一个可行的解决方案:按AbsCastLefttest.year排序,4为smallint-CastLeftt.year,4为smallint,CastLeftt.year,4为smallint,t.year desc,按差异排序,然后按有效年份递减,仍然相同的优先级记录按年份递增排序。这样,如果要更新的记录年份是2006年,那么2007年将先于2008年、2005年和2007年
感谢Lajos,这几乎是我所需要的,并且对于我目前的目的来说已经足够接近了。唯一轻微的问题是,通过按年份递减排序来优先考虑较新的年份,这也可以扭转上半年和下半年的顺序。如果可以避免,那么这将是一个完美的解决方案。在这种情况下,这似乎是一个可行的解决方案:按AbsCastLefttest.year排序,4为smallint-CastLeftt.year,4为smallint,CastLeftt.year,4为smallint,t.year desc,按差异排序,然后按有效年份递减,仍然相同的优先级记录按年份递增排序。这样,如果要更新的记录的年份是2006年,那么2007年将在2008年和2005年之前,2007年将在2007年之前。