Giải pháp không quan hệ
Tôi không nghĩ bất kỳ câu trả lời nào khác là đúng.
-
GROUP BY
sẽ không hoạt động -
Sử dụng
ROW_NUMBER()
buộc dữ liệu vào cấu trúc Hệ thống Lưu trữ Bản ghi, là cấu trúc vật lý, và sau đó xử lý nó dưới dạng các bản ghi vật lý. Với chi phí hiệu suất lớn. Tất nhiên, để viết mã như vậy, nó buộc bạn phải suy nghĩ về RFS thay vì suy nghĩ về Thuật ngữ quan hệ. -
Sử dụng CTE cũng vậy. Lặp đi lặp lại dữ liệu, đặc biệt là dữ liệu không thay đổi. Với chi phí lớn hơi khác một chút.
-
Con trỏ chắc chắn là thứ sai vì nhiều lý do khác nhau. (a) Con trỏ yêu cầu mã và bạn đã yêu cầu Chế độ xem (b) Con trỏ từ bỏ công cụ xử lý thiết lập và trở lại xử lý từng hàng. Một lần nữa, không bắt buộc. Nếu một nhà phát triển trong bất kỳ nhóm nào của tôi sử dụng con trỏ hoặc bảng tạm thời trên Cơ sở dữ liệu quan hệ (tức là không phải Hệ thống lưu hồ sơ), tôi sẽ bắn họ.
Giải pháp quan hệ
-
Dữ liệu của bạn là Quan hệ, lôgic, hai dữ liệu đã cho cột là tất cả những gì cần thiết.
-
Chắc chắn, chúng tôi phải tạo một Chế độ xem (Quan hệ dẫn xuất), để có được báo cáo mong muốn, nhưng báo cáo đó bao gồm các CHỌN thuần túy, điều này hoàn toàn khác với quá trình xử lý (chuyển đổi nó thành tệp , là vật lý và sau đó xử lý tệp ; hoặc bảng tạm thời; hoặc bảng làm việc; hoặc CTE; hoặc ROW_Number (); vv).
-
Trái ngược với những lời than thở của các "nhà lý thuyết", những người có một chương trình nghị sự, SQL xử lý dữ liệu quan hệ một cách hoàn hảo. Và dữ liệu của bạn là Quan hệ.
Do đó, hãy duy trì tư duy Quan hệ, quan điểm Quan hệ về dữ liệu và tư duy xử lý tập hợp. Mọi yêu cầu báo cáo trên Cơ sở dữ liệu quan hệ đều có thể được đáp ứng bằng cách sử dụng một CHỌN duy nhất. Không cần phải hồi quy về các phương pháp xử lý tệp ISAM trước năm 1970.
Tôi sẽ giả sử Khóa chính (tập hợp các cột cung cấp tính duy nhất cho hàng Quan hệ) là Date,
và dựa trên dữ liệu mẫu được cung cấp, Datatype là DATE.
Hãy thử điều này:
CREATE VIEW MyTable_Base_V -- Foundation View
AS
SELECT Date,
Date_Next,
Price
FROM (
-- Derived Table: project rows with what we need
SELECT Date,
[Date_Next] = DATEADD( DD, 1, O.Date ),
Price,
[Price_Next] = (
SELECT Price -- NULL if not exists
FROM MyTable
WHERE Date = DATEADD( DD, 1, O.Date )
)
FROM MyTable MT
) AS X
WHERE Price != Price_Next -- exclude unchanging rows
GO
CREATE VIEW MyTable_V -- Requested View
AS
SELECT [Date_From] = (
-- Date of the previous row
SELECT MAX( Date_Next ) -- previous row
FROM MyTable_V
WHERE Date_Next < MT.Date
),
[Date_To] = Date, -- this row
Price
FROM MyTable_Base_V MT
GO
SELECT *
FROM MyTable_V
GO
Phương pháp, Chung
Tất nhiên đây là một phương pháp, do đó nó là chung chung, nó có thể được sử dụng để xác định From_
và To_
của bất kỳ phạm vi dữ liệu nào (tại đây, một Date
phạm vi), dựa trên bất kỳ thay đổi dữ liệu nào (ở đây, thay đổi về Price
).
Đây, Date
của bạn liên tiếp, vì vậy việc xác định Date_Next
rất đơn giản:tăng Date
trước 1 ngày. Nếu PK đang tăng nhưng không liên tiếp (ví dụ:DateTime
hoặc TimeStamp
hoặc một số Khóa khác), thay đổi Bảng gốc X
tới:
-- Derived Table: project rows with what we need
SELECT DateTime,
[DateTime_Next] = (
-- first row > this row
SELECT TOP 1
DateTime -- NULL if not exists
FROM MyTable
WHERE DateTime > MT.DateTime
),
Price,
[Price_Next] = (
-- first row > this row
SELECT TOP 1
Price -- NULL if not exists
FROM MyTable
WHERE DateTime > MT.DateTime
)
FROM MyTable MT
Hãy tận hưởng.
Vui lòng bình luận, đặt câu hỏi, v.v.