Sử dụng Row_Number để tìm số hàng liên tiếp


8

Tôi có cột int này đại diện cho sự xuất hiện của tín hiệu và tôi đang cố gắng thêm một cột hiển thị số hàng liên tiếp

Nếu dữ liệu của tôi trông như thế này

724
727
728
733
735
737
743
747
749

dữ liệu kết quả với cột đếm hàng liên tiếp sẽ trông như thế này

724 1
727 1
728 2
729 3
735 1
737 1
743 1
744 2
748 1

Tôi đã thực hiện nó bằng cách sử dụng chức năng lặp nhưng tôi đang cố gắng tìm ra bằng cách sử dụng một cte. Đây là một mẫu của nỗ lực mới nhất của tôi

DECLARE @d TABLE ( signal INT )
INSERT  INTO @d
        SELECT  724
        UNION
        SELECT  727
        UNION
        SELECT  728
        UNION
        SELECT  729
        UNION
        SELECT  735
        UNION
        SELECT  737
        UNION
        SELECT  743
        UNION
        SELECT  744
        UNION
        SELECT  748 ;
WITH    a AS ( SELECT   signal,
                        ROW_NUMBER() OVER ( ORDER BY signal ) AS marker
               FROM     @d
             ) ,
        b AS ( SELECT   a1.signal,
                        CASE ( a1.signal - a2.signal )
                          WHEN 1 THEN 1
                          ELSE 0
                        END consecutiveMarker
               FROM     a a1
                        INNER JOIN a a2 ON a2.marker = a1.marker - 1
             )
    SELECT  *
    FROM    b

Tạo ra những kết quả này

signal  consecutiveMarker
727 0
728 1
729 1
735 0
737 0
743 0
744 1
748 0

Vấn đề rõ ràng đầu tiên là thiếu tín hiệu đầu tiên trong một chuỗi. Chặn điều đó, tôi nghĩ rằng sau đó tôi có thể chuyển cái này sang một cte khác với phân vùng row_number trên liên kếtMarker. Điều đó đã không làm việc bởi vì nó phân vùng nó như là một phân vùng. Tôi không thể tìm ra cách nào để chỉ ra phương pháp phân vùng rằng một chuỗi tách biệt với chuỗi tiếp theo

Bất kỳ trợ giúp được đánh giá cao.


1
Dường như có sự không phù hợp giữa dữ liệu nguồn và kết quả mong muốn.
Martin Smith

Câu trả lời:


16

Tên chung cho loại truy vấn này là "khoảng trống và đảo". Một cách tiếp cận dưới đây. Nếu bạn có thể có các bản sao trong dữ liệu nguồn, bạn có thể cần dense_rankthay vìrow_number

WITH DATA(C) AS
(
SELECT 724 UNION ALL
SELECT 727 UNION ALL
SELECT 728 UNION ALL
SELECT 729 UNION ALL
SELECT 735 UNION ALL
SELECT 737 UNION ALL
SELECT 743 UNION ALL
SELECT 744 UNION ALL
SELECT 747 UNION ALL
SELECT 749
), T1 AS
(
SELECT C,
       C - ROW_NUMBER() OVER (ORDER BY C) AS Grp
FROM DATA)
SELECT C,
       ROW_NUMBER() OVER (PARTITION BY Grp ORDER BY C) AS Consecutive
FROM T1

Trả về

C           Consecutive
----------- --------------------
724         1
727         1
728         2
729         3
735         1
737         1
743         1
744         2
747         1
749         1

1

Trong SQL 2012, bạn cũng có thể thực hiện việc này bằng LAG và các hàm cửa sổ, vd

DECLARE @d TABLE ( signal INT PRIMARY KEY) 

INSERT INTO @d 
VALUES
    ( 724 ),
    ( 727 ),
    ( 728 ),
    ( 729 ),
    ( 735 ),
    ( 737 ),
    ( 743 ),
    ( 744 ),
    ( 748 )

SELECT signal
    , 1 + ( SUM( is_group ) OVER ( ORDER BY signal ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING ) * is_group )
FROM
    (
    SELECT *
        , CASE WHEN LAG(signal) OVER( ORDER BY signal ) = signal - 1 THEN 1 ELSE 0 END is_group
    FROM @d
    ) x

-1

Như thường lệ với các vấn đề như vậy, rất dễ thực hiện trong Java hoặc C ++ hoặc C #.

Nếu bạn thực sự cần làm điều đó trong cơ sở dữ liệu, bạn có thể sử dụng RDBMS với các con trỏ nhanh, chẳng hạn như Oracle, viết một con trỏ đơn giản và tận hưởng hiệu suất nhanh mà không phải viết bất cứ điều gì phức tạp.

Nếu bạn cần thực hiện điều đó trong T-SQL và bạn không thể thay đổi thiết kế cơ sở dữ liệu, Itzik Ben-Gan đã viết ra một số giải pháp trong "MVP Deep Dives vol 1" và một số giải pháp mới sử dụng các hàm OLAP trong cuốn sách mới của mình về các chức năng của cửa sổ trong SQL 2012.

Ngoài ra, bạn có thể thêm một cột khácMarker vào bảng của mình và lưu trữ các giá trị được tính toán trước trong đó. Chúng tôi có thể sử dụng các ràng buộc để đảm bảo rằng dữ liệu được tính toán trước luôn hợp lệ. Nếu ai quan tâm, tôi có thể giải thích làm thế nào.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.