首页 > 解决方案 > SQL中的Vlookup

问题描述

我正在尝试编写一个查询,它将为帐户代码的每个段提取描述。该表如下所示:

当前表

我想要做的是让每个 CTRC 部分为匹配的 CTACCT 提取 CTDESC 示例:

我想要的结果

我的原始数据有超过 400 万行,所以我无法导出到 excel 以进行正常的 Vlookup。我只有一张包含所有这些数据的表,并且无法进行自我连接以提取所有行,我一次只能做一个部分。

SELECT TOP 10
       RTRIM(a.CTACCT) AS [CTACCT],
       RTRIM(a.CTRC01) AS [CTRC01],
       NULLIF(CONCAT(RTRIM(a.CTrc01), '-', RTRIM(a.CTrc02)), CONCAT(RTRIM(a.CTrc01), '-')) AS [CTRC02],
       NULLIF(CONCAT(RTRIM(a.CTrc01), '-', RTRIM(a.CTrc02), '-', RTRIM(a.CTrc03)), CONCAT(RTRIM(a.CTrc01), '-', RTRIM(a.CTrc02), '-')) AS [CTRC03],
       NULLIF(CONCAT(RTRIM(a.CTrc01), '-', RTRIM(a.CTrc02), '-', RTRIM(a.CTrc03), '-', RTRIM(a.CTrc04)), CONCAT(RTRIM(a.CTrc01), '-', RTRIM(a.CTrc02), '-', RTRIM(a.CTrc03), '-')) AS [CTRC04],
       NULLIF(CONCAT(RTRIM(a.CTrc01), '-', RTRIM(a.CTrc02), '-', RTRIM(a.CTrc03), '-', RTRIM(a.CTrc04), '-', RTRIM(a.CTrc05)), CONCAT(RTRIM(a.CTrc01), '-', RTRIM(a.CTrc02), '-', RTRIM(a.CTrc03), '-', RTRIM(a.CTrc04), '-')) AS [CTRC05],
       NULLIF(CONCAT(RTRIM(a.CTrc01), '-', RTRIM(a.CTrc02), '-', RTRIM(a.CTrc03), '-', RTRIM(a.CTrc04), '-', RTRIM(a.CTrc05), '-', RTRIM(a.CTrc06)), CONCAT(RTRIM(a.CTrc01), '-', RTRIM(a.CTrc02), '-', RTRIM(a.CTrc03), '-', RTRIM(a.CTrc04), '-', RTRIM(a.CTrc05), '-')) AS [CTRC06],
       a.CTDESC AS [CTDESC],
       a.CTSEGN AS [CTSEGN]
FROM [PSA].[dbo].[SMFD35_GLDBFA_GLPCT] a WITH (NOLOCK);

我正在使用 SQL Server。


标签: sql-serverjoinsql-server-2012vlookupself-join

解决方案


有几种方法可以做到这一点,因为您的表中已经有了值,一种方法是从原始表中添加一个 id 字段并标记 CTRC (LevelNr) 对应于结果中的 CTACCT:

select A.CTACCT, max(B.CTRC01) AS CTRC01, 
  max(case when B.LevelNr = 1 then B.Description else null end) AS CTRC01_Description,
  max(case when A.LevelNr >=2 then B.CTRC02 else null end) AS CTRC02, 
  max(case when A.LevelNr >=2 and B.LevelNr = 2 then B.Description else null end) AS CTRC02_Description,
  max(case when A.LevelNr >=3 then B.CTRC03 else null end) AS CTRC03, 
  max(case when A.LevelNr >=3 and B.LevelNr = 3 then B.Description else null end) AS CTRC03_Description
from @MyResults A
  inner join @MyResults B on A.id = B.id
group by A.[CTACCT], A.id, A.LevelNr
order by A.[CTACCT], A.id, A.LevelNr

结果:

CT_ACCT        CTRC01 CTRC01_Description CTRC02   CTRC02_Description CTRC03        CTRC03_Description
001            001    Company            NULL     NULL               NULL          NULL
001-0000       001    Company            001-0000 Department         NULL          NULL
001-0000-0000  001    Company            001-0000 Department         001-0000-0000 Location

不过,这实际上应该是关于数据库设计的讨论。如果您有单独存储每个 CTRC 值的数据,那么 STRING_AGG() 和 PIVOT 等分组函数就会发挥作用。

假设您可以使用 UNION 查询使您的数据处于如下状态:

id RowNr CTAcct
1  1     001
1  2     0000
1  3     0000
2  1     002
2  2     0000
2  3     0000

然后,您可以将所有帐号和描述放在一起,如下所示(STRING_AGG 更好,但 FOR XML 将为您的版本解决问题):

select [CTACCT], id, RowNr, Description
from
(
select RowNr, id,
  STUFF((SELECT '-' + [CTACCT]
    from @CTACCTS A where A.[id] = T.[id] and A.[RowNr] <= T.[RowNr]
    FOR XML PATH('')),1, 1,'') as [CTACCT]
from @CTACCTS T
) A left join @CTDESCRIPTIONS D ON A.[CTACCT] = D.[CTACCT]

结果:

CTACCT        id RowNr Description
001           1  1     Company
001-0000      1  2     Department
001-0000-0000 1  3     Location

最后,您可以执行与上述类似的操作,将事物重新组合在一起。这可能看起来像是额外的工作,但具有避免冗余的优点。

当然,您也可以执行一系列更新语句,但通常不建议在 SQL Server 中使用基于非集合的例程。


推荐阅读