2009-10-05 30 views
5

Tôi có một bộ dữ liệu có chứa:PostgreSQL và tuần tự dữ liệu

Table { date itemName } 

Ngày cho hầu hết các phần là tuần tự. Không có bản sao của ngày [vì nó là khóa chính].

Câu hỏi đặt ra là chia thành nhiều bộ phận (tất cả liên quan đến sử dụng SQL):

  1. Có thể tìm thấy lỗ hổng trong loạt ngày liệt kê trong bảng? Ví dụ: Ngày 1/2/09-1/3/09 bị thiếu
  2. Có thể tìm thấy các phần của ngày bị thiếu trong bảng, có phạm vi lớn hơn n (đây là số được xác định tại thời gian chạy) không? Ví dụ: Đối với n = 2 Ngày 1/2/09-1/3/09 không được trả lại nhưng Ngày 5/6/09-6/1/09 là.
+0

cách tiếp cận của tôi sẽ được gửi quá trình kết quả .. http://jeremy.zawodny.com/blog/archives/010523.html .. nhưng nếu nó có thể bên trong truy vấn, và không búa hệ thống quá xấu, đó sẽ là tuyệt vời :) – warren

+0

Đây không phải là một truy vấn trực tiếp sẽ được sử dụng thường xuyên, nó chỉ để bảo trì mỗi một lần và một lúc. – monksy

Trả lời

1

Chỉ cần tạo hàm trong plsql hoặc trong ứng dụng khách sẽ kiểm tra tất cả các ngày. Giống như mã giả này:

date checked_date = 2000-01-01; 
int unchecked_section = 0; 
while (checked_date <= today()) { 
    if (! sql(select itemName from Table where itemName=checked_date)) { 
    unchecked_section++; 
    } else { 
    if (unchecked_section>=n) { 
     print checked_date-unchecked_section, checked_date 
    } 
    unchecked_section = 0; 
    } 
    checked_date++; 
} 
if (unchecked_section) { 
    print checked_date-unchecked_section, checked_date 
} 

Nó không phải rất nhanh vì nó chỉ được bảo trì. Không có nhiều ngày để kiểm tra - chỉ 365 năm.

+0

Nếu bạn không có chức năng cửa sổ SQL, phương pháp này thực sự là phương thức nhanh nhất có thể trên một tập dữ liệu lớn, vì nó chỉ thực hiện một lần vượt qua bảng. Một điều bạn cần xem là SELECT được ORDER BY để các hàng xuất hiện theo thứ tự sắp xếp. Và bạn nên sử dụng "SELECT min (date), max (date) from table" để nhận giới hạn vòng lặp - giả sử mọi thứ kết thúc vào 'hôm nay' không phải là ý tưởng hay nhất. PostgreSQL có rất nhiều ngôn ngữ lập trình bạn có thể chạy bên trong cơ sở dữ liệu, PL/pgSQL là một ngôn ngữ chuẩn. –

1

Sau một số thử nghiệm tôi đã đưa ra các câu lệnh SQL sau:

SELECT date, itemName 
    FROM "Table" as t1 
    WHERE NOT EXISTS (
    SELECT date 
    FROM "Table" as t2 
    WHERE t2.date = (t1.date - INTERVAL '1 day') 
) 
    ORDER BY date 
    OFFSET 1 -- this will skip the first element 

Điều này sẽ giúp bạn có được tất cả các hàng mà không có người kế nhiệm trực tiếp.

Nếu bạn sửa đổi tuyên bố:

SELECT date, itemName 
    FROM "Table" as t1 
    WHERE NOT EXISTS (
    SELECT date 
    FROM "Table" as t2 
    WHERE (t2.date >= (t1.date - INTERVAL '2 day')) 
    AND (t2.date < t1.date) 
) 
    ORDER BY date 
    OFFSET 1 

bạn có thể sử dụng độ dài INTERVAL trong mệnh đề WHERE của subselect để lọc theo khoảng cách ít nhất là kích thước đó.

Hy vọng điều đó sẽ hữu ích.

+0

Thời gian chạy của tỷ lệ thuận với bình phương của kích thước bảng, vì cả hai lệnh SELECT bên ngoài và truy vấn con bên trong EXISTS đều làm những việc có thời gian chạy tỷ lệ thuận với kích thước của bảng. Điều đó có vẻ hợp lý lúc đầu, nhưng cuối cùng nó sẽ thực sự tốn kém. Thật không may, bất kỳ giải pháp khác mà bạn làm trong SQL thẳng sẽ phải chịu đựng cùng một vấn đề, bởi vì SQL không có bộ nhớ hàng. Đối với một bảng n-row, bạn phải làm một n n n để tham gia một số cách để giải quyết loại vấn đề này. Khi có sẵn, các chức năng cửa sổ là tốt nhất xung quanh điều này. –

+0

@Greg: Cảm ơn bạn đã phân tích.bạn nói đúng, đây không phải là giải pháp nhanh nhất, nếu cửa sổ functios đang ở trong tầm tay. Nhưng PostgreSQL 8.4 là một bản phát hành khá mới nên có nhiều cơ hội, OP đang sử dụng một phiên bản cũ hơn. Ngoài ra, hãy xem xét nhận xét của OP về câu hỏi của ông về các yêu cầu về hiệu suất thời gian chạy của ông. –

10

Nếu bạn có thể sử dụng PostgreSQL 8.4 sau đó window functions sẽ giúp:

SELECT * 
    FROM (SELECT itemName, date, date - lag(date) OVER w AS gap 
       FROM someTable WINDOW w AS (ORDER BY date) 
     ) AS pairs 
    WHERE pairs.gap > '1 day'::interval; 
+0

Đây chính là loại hàm cửa sổ có vấn đề có ý định giải quyết hiệu quả và không có giải pháp chỉ có SQL nào khác có thể chạy nhanh như thế này. –

+0

Thật không may, tôi không có phiên bản 8.4. Tôi có 8.1. Tôi ước tôi có thể nhận được tín dụng cho câu trả lời này. Tôi thực sự thích nó. – monksy

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