2017-11-03 120 views
13

Tôi có một bảng trong SQLServer 2008r2 như dưới đây.TSQL Nhóm theo Cột với nhiều giá trị

example dataset

Tôi muốn chọn tất cả các hồ sơ nơi [Fg] cột = 1 mà liên tục bởi [Id] để dẫn vào giá trị 2 cho mỗi sự kết hợp [T_Id][N_Id].

Có thể có trường hợp kỷ lục trước [Fg] = 2 không = 1

Có thể có bất kỳ số lượng hồ sơ, nơi giá trị của [Fg] = 1 nhưng chỉ có một kỷ lục mà [Fg] = 2 cho mỗi [T_Id][N_Id] kết hợp.

Vì vậy, ví dụ bên dưới, tôi muốn chọn các bản ghi với [Id] s (4,5) và (7,8,9) và (19,20).

Bất kỳ bản ghi nào cho [T_Id] 3 và 4 đều bị loại trừ.

Dự kiến ​​sản lượng

Expected output

Ví dụ dữ liệu thiết

DECLARE @Data TABLE (Id INT IDENTITY (1,1), T_Id INT, N_Id INT, Fg TINYINT) 

INSERT INTO @Data 
(T_Id, N_Id, Fg) 
VALUES 
(1, 2, 0), (1, 2, 1), (1, 2, 0), (1, 2, 1), (1, 2, 2), (2, 3, 0), (2, 3, 1), 
(2, 3, 1), (2, 3, 2), (3, 4, 0), (3, 4, 0), (3, 4, 0), (3, 4, 2), (4, 5, 0), 
(4, 5, 1), (4, 5, 0), (4, 5, 2), (5, 7, 0), (5, 7, 1), (5, 7, 2) 
+0

vì vậy, tất cả các bản ghi với FG 0 phải được lọc? Bởi vì nếu không 0, 1, 2 sẽ là một thứ tự đúng của việc truy tố hồ sơ, phải không? Và tại sao ID 7 được kỳ vọng là bản ghi chính xác vì ID 7 và 8 đều có FG 1? – Tyron78

+0

@ Tyron78 ​​bạn có thể có nhiều bản ghi liên tiếp trong đó FG = 1. Tôi đã giải thích điều này trong câu hỏi –

+0

Nhìn vào [ở đây] (https://blogs.msdn.microsoft.com/sqlreleaseservices/end-of-mainstream-support- cho-sql-server-2008-và-sql-server-2008-r2 /); tại sao sử dụng SQLServer 2008r2? –

Trả lời

12

Nó có thể được thực hiện dễ dàng bằng recursive CTE:

WITH DataSource AS 
(
    SELECT DS1.* 
    FROM @Data DS1 
    INNER JOIN @Data DS2 
     ON DS1.[T_Id] = DS2.[T_Id] 
     AND DS1.[N_Id] = DS2.[N_Id] 
     AND DS1.[Id] = DS2.[Id] + 1 
     AND DS1.[Fg] = 2 
     AND DS2.[Fg] = 1 
    UNION ALL 
    SELECT DS1.* 
    FROM @Data DS1 
    INNER JOIN DataSource DS2 
     ON DS1.[T_Id] = DS2.[T_Id] 
     AND DS1.[N_Id] = DS2.[N_Id] 
     AND DS1.[Id] = DS2.[Id] - 1 
     AND DS1.[Fg] = 1 
) 
SELECT * 
FROM DataSource 
ORDER BY Id 

enter image description here

Ý tưởng rất đơn giản. Phần đầu tiên của truy vấn nhận được tất cả các bản ghi valid với fg = 2 - có nghĩa là hợp lệ có bản ghi trước phiên bản này với fg = 1 từ cùng một nhóm.

Sau đó, trong phần đệ quy, chúng tôi nhận được tất cả các bản ghi nhỏ hơn những bản ghi ban đầu, có fg = 1.

+2

Thật tuyệt vời. Tôi đang cố gắng trong một thời gian dài. Cảm ơn bạn ... – DineshDB

+2

@gotqn Cảm ơn vì điều này. Tôi đã lộn xộn trong một thời gian dài với một giải pháp 'CROSS APPLY'. –

0

Bạn không thể sử dụng lag/lead vì nó bắt đầu trong SQL 2012, bạn sẽ cần phải làm một cái gì đó như dưới đây.

SELECT fg - (
     SELECT TOP 1 fg 
     FROM table m2 
     WHERE m2.fg = m1.fg-1 OR (m2.fg = m1.fg AND m2.id < m1.id) 
     ORDER BY 
       fg, id 
     ) 
FROM table m1 
ORDER BY 
     fg, id 
Các vấn đề liên quan