2012-05-01 35 views
5

Một đồng nghiệp của tôi có một vấn đề với một truy vấn sql: -Làm thế nào để thay thế NULL trong một tập kết quả với giá trị NOT NULL cuối cùng trong cùng một cột?

Lấy sau đây là một ví dụ, hai bảng tạm thời: -

select 'John' as name,10 as value into #names 
UNION ALL SELECT 'Abid',20 
UNION ALL SELECT 'Alyn',30 
UNION ALL SELECT 'Dave',15; 

select 'John' as name,'SQL Expert' as job into #jobs 
UNION ALL SELECT 'Alyn','Driver' 
UNION ALL SELECT 'Abid','Case Statement'; 

Chúng tôi chạy truy vấn sau trên bảng để cung cấp cho chúng ta một joinet resultset: -

select #names.name, #names.value, #jobs.job 
FROM #names left outer join #jobs 
on #names.name = #jobs.name 

name value job 
John 10  SQL Expert 
Abid 20  Case Statement 
Alyn 30  Driver 
Dave 15  NULL 

Vì 'Dave' không tồn tại trong bảng #jobs, anh ta được cung cấp giá trị NULL như mong đợi.

Đồng nghiệp của tôi muốn sửa đổi truy vấn để mỗi giá trị NULL được cung cấp cùng giá trị với mục nhập trước đó.

Vì vậy, bên trên sẽ là: -

name value job 
John 10  SQL Expert 
Abid 20  Case Statement 
Alyn 30  Driver 
Dave 15  Driver 

Lưu ý rằng Dave bây giờ là một 'điều khiển'

Có thể có nhiều hơn một giá trị NULL theo thứ tự,

name value job 
John 10  SQL Expert 
Abid 20  Case Statement 
Alyn 30  Driver 
Dave 15  NULL 
Joe  15  NULL 
Pete 15  NULL 

Trong trường hợp này Dave, Joe và Pete tất cả nên là 'Driver', vì 'Driver' là mục nhập không phải là lần cuối.

+2

có ràng buộc về đơn đặt hàng hay là trình điều khiển Dave, Joe và Pete chỉ vì chúng được trả tự do sau Alyn? – GolfWolf

+2

Đây là điều bạn có thể muốn thực hiện trong mã thay thế. – Magnus

+0

Trong ví dụ hiện tại không có thứ tự, vì vậy có chỉ tự ý quay trở lại. –

Trả lời

6

Có thể có những cách tốt hơn để thực hiện việc này. Dưới đây là một trong những cách tôi có thể đạt được kết quả bằng cách sử dụng Common Table Expressions (CTE) và sử dụng đầu ra đó để thực hiện một số OUTER APPLY để tìm công việc của người viết trước đó. Truy vấn ở đây sử dụng id để sắp xếp các bản ghi và sau đó xác định công việc của người trước đó. Bạn cần ít nhất một tiêu chí để sắp xếp các bản ghi vì dữ liệu trong các bảng được coi là các bộ không theo thứ tự.

Ngoài ra, giả định là người đầu tiên trong chuỗi sẽ có công việc. Nếu người đầu tiên không có việc làm, thì không có giá trị để chọn.

Click here to view the demo in SQL Fiddle.

Click here to view another demo in SQL Fiddle with second data set.

Script:

CREATE TABLE names 
    (
      id  INT   NOT NULL IDENTITY 
     ,  name VARCHAR(20) NOT NULL 
     ,  value INT   NOT NULL 
    ); 

    CREATE TABLE jobs 
    (
      id INT   NOT NULL 
     ,  job VARCHAR(20) NOT NULL 
    ); 

    INSERT INTO names (name, value) VALUES 
     ('John', 10), 
     ('Abid', 20), 
     ('Alyn', 30), 
     ('Dave', 40), 
     ('Jill', 50), 
     ('Jane', 60), 
     ('Steve', 70); 

    INSERT INTO jobs (id, job) VALUES 
     (1, 'SQL Expert'), 
     (2, 'Driver'), 
     (5, 'Engineer'), 
     (6, 'Barrista'); 

    ;WITH empjobs AS 
    (
     SELECT 
     TOP 100 PERCENT n.id 
        , n.name 
        , n.value 
        , job 
     FROM   names n 
     LEFT OUTER JOIN jobs j 
     on    j.id = n.id 
     ORDER BY  n.id 
    ) 
    SELECT  e1.id 
      , e1.name 
      , e1.value 
      , COALESCE(e1.job , e2.job) job FROM empjobs e1 
    OUTER APPLY (
        SELECT 
        TOP 1  job 
        FROM  empjobs  e2 
        WHERE  e2.id < e1.id 
        AND  e2.job IS NOT NULL 
        ORDER BY e2.id DESC 
       ) e2; 

Output:

ID NAME VALUE JOB 
--- ------ ----- ------------- 
1 John  10 SQL Expert 
2 Abid  20 Driver 
3 Alyn  30 Driver 
4 Dave  40 Driver 
5 Jill  50 Engineer 
6 Jane  60 Barrista 
7 Steve  70 Barrista 
+0

+1 Tôi không biết về SQLFiddle. Ngoài ra, giải pháp tuyệt vời! – GolfWolf

+1

CHỌN TOP 100 PERCENT .. ORDER BY trong CTE, chế độ xem hoặc truy vấn phụ không có hiệu lực. Nhiều năm trước, nó thường được bảo đảm một trật tự, nhưng điều đó không bao giờ được ghi lại, và nó không thể dựa vào để làm bất cứ điều gì cả. –

+0

Phiên bản sửa đổi ở trên đã thực hiện công việc một cách độc đáo. Cảm ơn. –

0

gì yo u có nghĩa là bởi "cuối cùng" không null nhập? Bạn cần một thứ tự được xác định rõ ràng cho "cuối cùng" để có một ý nghĩa nhất quán. Đây là truy vấn có định nghĩa dữ liệu sử dụng cột "giá trị" để xác định cuối cùng và có thể gần với những gì bạn muốn.

CREATE TABLE #names 
    (
      id  INT   NOT NULL IDENTITY 
     ,  name VARCHAR(20) NOT NULL 
     ,  value INT   NOT NULL PRIMARY KEY 
    ); 

    CREATE TABLE #jobs 
    (
      name VARCHAR(20)   NOT NULL 
     ,  job VARCHAR(20) NOT NULL 
    ); 

    INSERT INTO #names (name, value) VALUES 
     ('John', 10), 
     ('Abid', 20), 
     ('Alyn', 30), 
     ('Dave', 40), 
     ('Jill', 50), 
     ('Jane', 60), 
     ('Steve', 70); 

    INSERT INTO #jobs (name, job) VALUES 
     ('John', 'SQL Expert'), 
     ('Abid', 'Driver'), 
     ('Alyn', 'Engineer'), 
     ('Dave', 'Barrista'); 

with Partial as (
    select 
    #names.name, 
    #names.value, 
    #jobs.job as job 
    FROM #names left outer join #jobs 
    on #names.name = #jobs.name 
) 
    select 
    name, 
    value, 
    (
     select top 1 job 
     from Partial as P 
     where job is not null 
     and P.value <= Partial.value 
     order by value desc 
    ) 
    from Partial; 

Có thể chèn dữ liệu hiệu quả hơn, sau đó cập nhật.

Các vấn đề liên quan