我需要将表A转换为表B(即用每列的先前非空值填充所有空值)
主要任务是用每列以前的非空值填充空值。
这是原始表:
FromCompany Container Numbers ToCompany Location
DISCOVERY HALU 330308 5 MAGNA CHARGE St-Laurent
ATSU 827944 0 LEEZA DIST.
4
COLUMBIA CAIU 807457 3 La Cie Canada Baie D'Urfe
6
0
决赛桌应该是:
FromCompany Container Numbers ToCompany Location
DISCOVERY HALU 330308 5 MAGNA CHARGE St-Laurent
DISCOVERY ATSU 827944 0 LEEZA DIST St-Laurent
DISCOVERY ATSU 827944 4 LEEZA DIST St-Laurent
COLUMBIA CAIU 807457 3 La Cie Canada Baie D'Urfe
COLUMBIA CAIU 807457 6 La Cie Canada Baie D'Urfe
COLUMBIA CAIU 807457 0 La Cie Canada Baie D'Urfe
我们将不胜感激。
答案 0 :(得分:2)
在很大程度上,您确实需要一列来对数据集进行排序。由于您的数据来自CSV文件,因此,例如,您可以在加载文件之前先对其进行编辑,以添加自动递增的行号。
假设您已使用此列(Random
),这是一个SQLServer解决方案,用于使用相同的第一个非0x5deece66dL
值填充id
值的问题列。
基本思想是将每条记录放入一个组,其编号对应于具有非空值的第一条记录的ID。要填充5列,我们需要5组。
NULL
返回:
id | FromCompany | Container | Numbers | ToCompany | Location | grpFromCompany | grpContainer | grpNumbers | grpToCompany | grpLocation -: | :---------- | :---------- | ------: | :------------ | :---------- | -------------: | -----------: | ---------: | -----------: | ----------: 1 | DISCOVERY | HALU 330308 | 5 | MAGNA CHARGE | St-Laurent | 1 | 1 | 1 | 1 | 1 2 | null | ATSU 827944 | 0 | LEEZA DIST. | null | 1 | 2 | 2 | 2 | 1 3 | null | null | 4 | null | null | 1 | 2 | 3 | 2 | 1 4 | COLUMBIA | CAIU 807457 | 3 | La Cie Canada | Baie D'Urfe | 4 | 4 | 4 | 4 | 4 5 | null | null | 6 | null | null | 4 | 4 | 5 | 4 | 4 6 | null | null | 0 | null | null | 4 | 4 | 6 | 4 | 4
现在我们可以将其转换为CTE,并使用它来查找表中的相关值:
NULL
id | FromCompany | Container | Numbers | ToCompany | Location -: | :---------- | :---------- | ------: | :------------ | :---------- 1 | DISCOVERY | HALU 330308 | 5 | MAGNA CHARGE | St-Laurent 2 | DISCOVERY | HALU 330308 | 0 | LEEZA DIST. | St-Laurent 3 | DISCOVERY | HALU 330308 | 4 | LEEZA DIST. | St-Laurent 4 | COLUMBIA | CAIU 807457 | 3 | La Cie Canada | Baie D'Urfe 5 | COLUMBIA | CAIU 807457 | 6 | La Cie Canada | Baie D'Urfe 6 | COLUMBIA | CAIU 807457 | 0 | La Cie Canada | Baie D'Urfe
db <>提琴here
答案 1 :(得分:0)
通常,如果您的表具有标识列或保证行排序的方法,则可以使用CTE相对有效地实现此目的。但是,我们这里没有那么奢侈,所以另一个解决方案是改用效率低得多的CURSOR
。
-- Cursor variables
DECLARE @FromCompanyCursor varchar(20),
@ContainerCursor varchar(20),
@NumbersCursor int,
@ToCompanyCursor varchar(20),
@LocationCursor varchar(20),
@FromCompany varchar(20),
@Container varchar(20),
@Numbers int,
@ToCompany varchar(20),
@Location varchar(20);
-- Cursor declaration
DECLARE C CURSOR FOR
(
SELECT FromCompany,
Container,
Numbers,
ToCompany,
Location
FROM TableName
)
FOR UPDATE OF FromCompany, Container, Numbers, ToCompany, Location;
OPEN C;
-- Get first row from the cursor
FETCH NEXT FROM C INTO @FromCompanyCursor, @ContainerCursor, @NumbersCursor, @ToCompanyCursor, @LocationCursor;
-- While we still have rows to iterate over
WHILE @@FETCH_STATUS = 0
BEGIN
-- Keep track of the last non-null value
SELECT @FromCompany = CASE WHEN @FromCompanyCursor IS NOT NULL THEN @FromCompanyCursor ELSE @FromCompany END,
@Container = CASE WHEN @ContainerCursor IS NOT NULL THEN @ContainerCursor ELSE @Container END,
@Numbers = CASE WHEN @NumbersCursor IS NOT NULL THEN @NumbersCursor ELSE @Numbers END,
@ToCompany = CASE WHEN @ToCompanyCursor IS NOT NULL THEN @ToCompanyCursor ELSE @ToCompany END,
@Location = CASE WHEN @LocationCursor IS NOT NULL THEN @LocationCursor ELSE @Location END;
-- Update the table with the last non-null values
UPDATE TableName
SET FromCompany = @FromCompany,
Container = @Container,
Numbers = @Numbers,
ToCompany = @ToCompany,
Location = @Location
WHERE CURRENT OF C;
-- Get the next row from the cursor
FETCH NEXT FROM C INTO @FromCompanyCursor, @ContainerCursor, @NumbersCursor, @ToCompanyCursor, @LocationCursor;
END
-- Don't forget to close the cursor!
CLOSE C;
DEALLOCATE C;
请注意,此类基于过程的操作在SQL Server中效率极低,因此,此类解决方案应用作一次性操作或作为计划维护工作的一部分。