2010-11-01 42 views
12

Tôi có hai bảng trong SQL và tôi cần có khả năng thực hiện tham gia dựa trên dấu thời gian trong bảng B sớm hơn hoặc bằng dấu thời gian trong bảng A.Truy vấn SQL để tham gia hai bảng dựa trên dấu thời gian gần nhất

vì vậy, đây là một số dữ liệu giả cho hai bảng và đầu ra mong muốn:

các trường hợp

Đóng (Bảng A)

 
| id | resolution |   timestamp   | 
------------------------------------------------ 
| 1 |  solved | 2006-10-05 11:55:44.888153 | 
| 2 |  closed | 2007-10-07 12:34:17.033498 | 
| 3 | trashed | 2008-10-09 08:19:36.983747 | 
| 4 |  solved | 2010-10-13 04:28:14.348753 | 

Phân loại (Bảng B)

 

| id | value |   timestamp   | 
------------------------------------------------- 
| 1 | freshman | 2006-01-01 12:02:44.888153 | 
| 2 | sophomore | 2007-01-01 12:01:19.984333 | 
| 3 |  junior | 2008-01-01 12:02:28.746149 | 

kết quả mong muốn

 
| id | resolution |   timestamp   | value | 
-------------------------------------------------------------- 
| 1 |  solved | 2006-10-05 11:55:44.888153 | freshman | 
| 2 |  closed | 2007-10-07 12:34:17.033498 | sophomore | 
| 3 | trashed | 2008-10-09 08:19:36.983747 |  junior | 
| 4 |  solved | 2010-10-13 04:28:14.348753 |  junior | 

Vì vậy, tôi biết mã cần nhìn như sau, tôi chỉ không thể tìm ra phải làm gì với phần ON của JOIN ($ 1 và 2 đô la là các biến số sẽ được chuyển vào):

SELECT case.id, case.resolution, case.timestamp, class.value 
    FROM closed_cases AS case 
    LEFT JOIN classifications AS class ON ??? 
    WHERE case.timestamp BETWEEN $1 AND $2; 

Tôi biết tôi có thể sử dụng một lựa chọn phụ, nhưng điều này sẽ hoạt động tại le ast một vài nghìn hàng, có lẽ nhiều hơn, và tôi cần nó rất nhanh; vì vậy tôi đã hy vọng cho một mệnh đề đơn giản có thể làm điều đó.

+0

Tôi nghĩ rằng bạn sẽ cần phụ chọn của bạn. Bạn đã thử nghiệm hiệu suất và thấy nó không thể chấp nhận? – Beth

+0

nếu phiên bản SQL bạn đang sử dụng hỗ trợ chức năng phân tích cửa sổ, bạn có thể thực hiện nó mà không cần chọn phụ, nhưng một số phiên bản của SQL không hỗ trợ chúng. Đối với một lựa chọn phụ trên một vài nghìn hàng, hiệu suất không được quá tệ. (Việc lựa chọn phụ sẽ được trên bảng phân loại - điều này thực sự sẽ có nhiều hơn một vài nghìn hàng?) –

+0

@Mark - Thực ra, hãy nghĩ về nó, bảng phân loại phải có hàng ít hơn so với tôi kiểm tra xem liệu dữ liệu đã thực sự thay đổi từ phiên bản mới nhất chưa.Vì vậy, tôi đoán phụ chọn sẽ làm việc tốt, nhưng tôi nghĩ rằng việc thêm thời gian kết thúc là một giải pháp sạch hơn. –

Trả lời

7

Nếu bạn có thể thay đổi cấu trúc bảng, tôi khuyên bạn nên thay đổi bảng phân loại để bao gồm ngày kết thúc cũng như ngày bắt đầu - sẽ dễ dàng hơn khi tham gia vào bảng theo cách đó.

Nếu không, tôi đề nghị như sau:

SELECT case.id, case.resolution, case.timestamp, class.value 
    FROM closed_cases AS case 
    LEFT JOIN (select c.*, 
        (select min(timestamp) 
        from classifications c1 
         where c1.timestamp > c.timestamp) timeend 
      from classifications c) AS class 
    ON case.timestamp >= class.timestamp and 
    (case.timestamp < class.timeend or class.timeend IS NULL) 
    WHERE case.timestamp BETWEEN $1 AND $2; 

EDIT - với ngày kết thúc trên phân loại:

SELECT case.id, case.resolution, case.timestamp, class.value 
    FROM closed_cases AS case 
    LEFT JOIN classifications AS class 
    ON case.timestamp >= class.timestamp and case.timestamp < class.timeend 
    WHERE case.timestamp BETWEEN $1 AND $2; 
+0

Bạn có thể giải thích ngắn gọn cách thay đổi cấu trúc bảng bao gồm ngày kết thúc sẽ giúp ích không? Tôi về mặt lý thuyết có thể làm điều này bằng cách luôn đặt ngày kết thúc hiện tại là một khoảng thời gian thực sự xa trong tương lai và cập nhật ngày kết thúc của mục nhập trước đó là ngày bắt đầu mục nhập hiện tại. –

+0

@Topher - truy vấn bổ sung được thêm vào; không có lựa chọn phụ là bắt buộc và truy vấn nên được sargable. –

+0

+ 1/Đã chấp nhận - Cảm ơn sự giúp đỡ của Mark! Tôi sẽ chỉ thêm thời gian kết thúc để làm cho cuộc sống dễ dàng hơn. –

0

thay đổi dấu thời gian và sử dụng int làm khóa để kết nối các bảng. điều này sẽ làm việc nhanh hơn nhiều sau đó so sánh ngày

bảng 1 field1 field2 field3 ConnectorField

table2 field1 field2 field3 ConnectorField

và tất cả các bạn cần làm là select * from table1 T1 bên trong tham gia table2 T2 trên T1.ConnectorField = T2.ConnectorField

+0

Giải pháp này yêu cầu OP có thể thay đổi cấu trúc của cơ sở dữ liệu hiện có và sẽ ngăn các thay đổi trong phạm vi ngày phân loại so với các trường hợp hiện có. –

+0

Nó không quan trọng hay không tôi sử dụng một số nguyên (không phải là dấu thời gian được lưu trữ dưới dạng số nguyên anyway), điều này vẫn không giải quyết được vấn đề "gần nhất". Tôi vẫn sẽ cần phải làm việc tham gia dựa trên chính xác một số nguyên trong bảng B đó là nhỏ hơn hoặc bằng số nguyên trong bảng A. –

+0

@Topher, có lẽ tôi đã không hiểu các đặc điểm kỹ thuật. – none

-1
SELECT case.id, case.resolution, case.timestamp, class.value 
    FROM closed_cases AS case 
    LEFT JOIN classifications AS class 
    ON case.timestamp >= class.timestamp 
    WHERE case.timestamp BETWEEN $1 AND $2; 
+0

Điều này sẽ trả về tất cả các phân loại sau dấu thời gian cho mỗi trường hợp, thay vì chỉ phân loại áp dụng - vì vậy cho ví dụ được cung cấp, bạn sẽ thấy 11 hàng được trả về thay vì 4 hàng được yêu cầu. –

+0

@Mark Mannister - Chính xác. Tôi chỉ cần 4 hàng (tôi sẽ làm đếm và nhóm chúng sau). –

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