链接0个或多个丢失的数据字段

时间:2013-05-09 15:50:27

标签: sql-server tsql join jointable

我有一个巨大的主表(1tb数据)和超过20列。我有0个或更多丢失数据字段的源数据。我必须通过匹配主表中的可用字段来填写缺少的数据。请考虑以下示例:

传入数据:

 CREATE TABLE #t1 ( f3 VARCHAR(50), f1 INT, f2 INT )
    INSERT INTO #t1 
    SELECT 'Row1',1, NULL 
    UNION ALL 
    SELECT 'Row2', 1, 2 

主表:

CREATE TABLE #t2 ( f1 INT, f2 INT, f3 INT, f4 VARCHAR(255)  ) 

INSERT INTO #t2 
SELECT 1, 2, 3, 'A' 
UNION ALL 
SELECT 1, 2, 4, 'B' 
UNION ALL 
SELECT 1, 3, 3, 'C' 
UNION ALL 
SELECT 1, 3, 4, 'D' 
UNION ALL 
SELECT 2, 3, 4, 'E' 

我希望输出将Row1链接到行A,B,C和D以及行2链接到行A和B.我可以通过以下方式实现此目的:

SELECT a.f3, b.* 
FROM   #t2 b 
       CROSS JOIN #t1 a 
WHERE  Patindex(Isnull(CONVERT(CHAR(1), a.f1), '_') + Isnull(CONVERT(CHAR(1), a.f2), '_')
                , CONVERT(CHAR(1), b.f1) + CONVERT(CHAR(1), b.f2)) != 0 

DROP TABLE #t1 
DROP TABLE #t2 

这不是一个非常可扩展的解决方案,因为当我有20个字段时,它将变成冗长而复杂的SQL。

有更好的解决方案吗?

1 个答案:

答案 0 :(得分:0)

这是交易的“一招”。

更新所有列,但是如果没有为潜在更新值给出值(空值)....忽略它并使用原始值....使用CASE语句。

您原来帖子中的语言有点令人困惑。

我认为“字段”你的意思是“列”.......(我不是在挑剔,我试图区分列和“列中的值”。)< / p>

也许以下内容可以提供帮助。

这是一个通用的Northwind示例

Use Northwind
GO



IF OBJECT_ID('tempdb..#OrderDetailsHolder') IS NOT NULL
begin
        drop table #OrderDetailsHolder
end


CREATE TABLE #OrderDetailsHolder
(
IdentityKey int not null identity (1001, 1), 
[OrderID] int, 
[ProductID] int,
[UnitPrice] money
)


INSERT INTO #OrderDetailsHolder ( OrderID, ProductID , UnitPrice ) 
Select top 10 OrderID, ProductID , UnitPrice from dbo.[Order Details] where UnitPrice IS NOT NULL


print 'Before massaged data look'
select * from #OrderDetailsHolder

Update #OrderDetailsHolder Set [UnitPrice] = null where IdentityKey < 1006
Update #OrderDetailsHolder Set [UnitPrice] = ([UnitPrice] * 1.333) where IdentityKey >= 1006


print 'After massaged data look'
select * from #OrderDetailsHolder


/* 
Here is the magic (below query).  
If [UnitPrice] is NULL in the "holder" temp table, then KEEP THE ORIGINAL value.  
If the UnitPrice is NOT null in the temp table, update using the holder-temp table UnitPrice value.
*/

Update dbo.[Order Details] 
Set [UnitPrice] = CASE
                    WHEN holder.[UnitPrice] IS NOT NULL then holder.UnitPrice
                    ELSE realTable.UnitPrice
                END
FROM    
    #OrderDetailsHolder holder , dbo.[Order Details] realTable
Where
    holder.OrderID = realTable.OrderID and holder.ProductID = realTable.ProductID



/* Now show the real table data, which should have 5 rows as having different UnitPrice values */

Select * from   #OrderDetailsHolder holder join dbo.[Order Details] realTable
    on holder.OrderID = realTable.OrderID and holder.ProductID = realTable.ProductID






IF OBJECT_ID('tempdb..#OrderDetailsHolder') IS NOT NULL
begin
        drop table #OrderDetailsHolder
end