T-SQL"加入"表到另一个并收集前三个记录作为列

时间:2015-03-31 00:26:11

标签: sql-server tsql

我无法想出一个更好的方法来说明这一点。

我有几张桌子:

Postcode | One | Two | Three
2000     |     |     |
2001     |     |     |
2002     |     |     |

等,此表中有10,000个邮政编码,OneTwoThree列均为空。

我有另一张这样的表:

Postcode | details
2001     | "foo"
2020     | "bar"

基本上,第二个表有一些选择的邮政编码,以及一些东西。让我们说那里有2000个邮政编码。

我想要做的,我知道它不理想,填充第一个表的三个额外列,第二个表中的邮政编码在数字上最接近它(无论是更大的还是更小)。

到目前为止,我已经完成了这项工作(我的Postcode列是varchar}:

SELECT 
    A.Postcode
    , ( SELECT 
            MAX(X.Postcode)
        FROM (
            SELECT
                CAST(B.Postcode AS INT) AS 'Postcode'
                , RANK() OVER (ORDER BY CAST(B.Postcode AS INT) ASC) AS 'rank'
            FROM [TableB] B with(nolock)
            WHERE CAST(B.Postcode AS INT) >= CAST(A.Postcode AS INT)
        ) X WHERE X.[rank] = 1
    ) AS ONE
FROM [TableA] A with(nolock)

这让我获得了第一个更高的邮政编码。但我需要它更高或更低,我需要三个,而不仅仅是一个。

我被困在这里。

1 个答案:

答案 0 :(得分:3)

您可以使用ROW_NUMBERCROSS APPLY的组合:

SQL Fiddle

SELECT
    a.PostCode,
    b.One,
    b.Two,
    b.Three
FROM TableA a
CROSS APPLY(
    SELECT
        One = MAX(CASE WHEN RN = 1 THEN x.PostCode END),
        Two = MAX(CASE WHEN RN = 2 THEN x.PostCode END),
        Three = MAX(CASE WHEN RN = 3 THEN x.PostCode END)
    FROM(
        SELECT *, 
            RN = ROW_NUMBER() OVER(ORDER BY CAST(t.PostCode AS INT))
        FROM(
            SELECT TOP 3 
                PostCode,
                Diff = ABS(CAST(PostCode AS INT) - CAST(a.PostCode AS INT))
            FROM Tableb
            WHERE
                PostCode <> a.PostCode
            ORDER BY ABS(CAST(PostCode AS INT) - CAST(a.PostCode AS INT)), CAST(PostCode AS INT)
        )t
    )x
)b

<强>结果

PostCode   One        Two        Three
---------- ---------- ---------- ----------
2000       2001       2002       2003
2001       2000       2002       2003
2002       2000       2001       2003

示例数据

表A

PostCode   One        Two        Three
---------- ---------- ---------- ----------
2000       NULL       NULL       NULL
2001       NULL       NULL       NULL
2002       NULL       NULL       NULL

表B

PostCode
----------
2000
2001
2002
2003
2004
2005
2006
2007
2008