Giải thích một mệnh đề QUÁ


7

Tôi thấy một tuyên bố TSQL ngắn gọn có hiệu quả phân tách một chuỗi thành các ký tự cấu thành của nó, mỗi chuỗi trên một dòng, nhằm mục đích đánh asciigiá giá trị trên mỗi ký tự.

Nếu tôi đang đọc truy vấn một cách chính xác, hiệu quả, 3 CTE đang được sử dụng để chuẩn bị một bảng gồm 1 cột chứa 10.000 hàng, mỗi hàng có giá trị '0'.

CTE thứ tư được định nghĩa như sau:

cteTally(n) AS(
    SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) n 
    FROM E4
)

Sau đó, CTE này được nối với một bảng chứa một cột có các chuỗi quan tâm, với các mục sau select:

SELECT n, SUBSTRING(LastName, n, 1), ASCII( SUBSTRING(LastName, n, 1))

Đó là, hàng số n, sau đó là ký tự thứ n trong LastName, sau đó là giá trị ascii của ký tự đó.

Các câu hỏi của tôi liên quan đến overmệnh đề trong CTE ở trên.

Về cơ bản, chính xác thì nó đang làm gì?

Nếu chúng ta đang truy vấn row_number từ 10.000 hàng giống nhau, tại sao chúng ta cần một order bymệnh đề? Tại sao mệnh đề order byđược đặt vào một overmệnh đề chứ không phải là một order bymệnh đề cho selectcâu lệnh - đặc biệt là overmệnh đề thậm chí không chỉ định bất kỳ phân vùng nào? (Tôi đoán điều này có nghĩa là cửa sổ trên đó row_numberhoạt động đủ 10.000 hàng?) Và ý nghĩa của việc đặt hàng là select nullgì?

Câu trả lời:


8

ROW_NUMBER () là một hàm cửa sổ xếp hạng và các hàm cửa sổ xếp hạng yêu cầu mệnh đề ORDER BY bắt buộc. Nếu bạn cố gắng viết nó mà không có ĐẶT HÀNG, bạn sẽ gặp lỗi cú pháp.

SELECT ROW_NUMBER() OVER()
FROM (VALUES ('A'), ('B'), ('C')) AS X(Y);
-- Msg 4112, Level 15, State 1, Line 1 
-- The function 'ROW_NUMBER' must have an OVER clause with ORDER BY.

Thủ thuật với truy vấn con được phát hiện bởi một người viết blog về nó, như là một tối ưu hóa hiệu suất. SQL Server luôn thực hiện một hoạt động sắp xếp vì các hằng số không được phép cho mệnh đề ORDER BY:

SELECT ROW_NUMBER() OVER(ORDER BY NULL)
FROM (VALUES ('A'), ('B'), ('C')) AS X(Y);
-- Msg 5309, Level 16, State 1, Line 1
-- Windowed functions, aggregates and NEXT VALUE FOR functions 
-- do not support constants as ORDER BY clause expressions.

Và cũng không phải là số nguyên được coi là chỉ số:

SELECT ROW_NUMBER() OVER(ORDER BY 1)
FROM (VALUES ('A'), ('B'), ('C')) AS X(Y);
-- Msg 5308, Level 16, State 1, Line 1
-- Windowed functions, aggregates and NEXT VALUE FOR functions 
-- do not support integer indices as ORDER BY clause expressions.

Hóa ra là do một số trục trặc trong mã, bạn có thể phá vỡ giới hạn này bằng cách sử dụng truy vấn con, vì lý do nào đó được cho phép và loại bỏ toán tử sắp xếp.

SELECT ROW_NUMBER() OVER(ORDER BY (SELECT 1))
FROM (VALUES ('A'), ('B'), ('C')) AS X(Y);

Không có toán tử sắp xếp

Bạn có thể sử dụng bất kỳ hằng số nào trong truy vấn phụ, NULL có thể gợi nhớ đến thói quen sử dụng CHỌN NULL trong các vị từ EXISTS, trong lịch sử ban đầu của SQL Server có tác động hiệu năng trái ngược với * hoặc bất kỳ biểu thức cột nào khác, như trình tối ưu hóa không đủ thông minh để bỏ qua nó.

HTH

CẬP NHẬT @ Erik-Darling nhận xét rằng bạn cũng có thể phá vỡ nó bằng cách sử dụng một biểu thức được tính toán:

You can do SELECT ROW_NUMBER() OVER (ORDER BY 1/0);

Cảm ơn bạn. Chắc chắn là có. Tôi có thể thấy hầu hết các câu hỏi của mình rơi vào như một ngôi nhà thẻ trên "các chức năng của windows yêu cầu một thứ tự bắt buộc theo mệnh đề". Các tài liệu MS trong overmệnh đề nói order bylà tùy chọn - nhưng tôi đoán điều này có nghĩa là các phân vùng có thể được sử dụng mà không có chức năng cửa sổ (và không yêu cầu order by). Tên người dùng tốt đẹp!
youcantryreachingme

3
Không phải tất cả các chức năng cửa sổ yêu cầu một ORDER BY. Chỉ xếp hạng các chức năng cửa sổ - ROW_NUMBER(), RANK(), DENSE_RANK(), NTILE(). Cung cấp một PARTITION BYhoặc không là không liên quan.
ypercubeᵀᴹ

2
Bạn có thể làmSELECT ROW_NUMBER() OVER (ORDER BY 1/0);
Erik Darling

4

Mệnh đề OVER đặt thứ tự (và phân vùng nếu được bao gồm PHẦN THAM GIA) của bộ hàng trước khi áp dụng chức năng Windowing đã chọn. Vì bạn có thể sử dụng nhiều hàm Window trong một truy vấn duy nhất, mỗi hàm yêu cầu phân vùng và sắp xếp riêng để đảm bảo dữ liệu được trả về như mong muốn.

Trong ví dụ của bạn, ROW_NUMBER () đang được sử dụng để tạo số hàng liên tiếp cho mỗi hàng trong CTE. CHỌN NULL được sử dụng vì không có yêu cầu cụ thể nhưng mệnh đề ORDER BY được yêu cầu cho chức năng cửa sổ.

Tuy nhiên, một cách khác để đạt được điều tương tự là sử dụng cột IDENTITY, tuy nhiên, điều đó có ý nghĩa khác và yêu cầu thay đổi đối với bảng hiện có hoặc bảng tạm thời được tạo. Chức năng cửa sổ ROW_NUMBER trong CTE cho phép tạo danh tính này khi đang di chuyển.

Để trả lời câu hỏi cụ thể của bạn:

Về cơ bản, chính xác thì nó đang làm gì?

Nó đang sắp xếp các hàng trong E4 'ngẫu nhiên' trước khi áp dụng hàm cửa sổ ROW_NUMBER () cho tập kết quả đó để tạo danh sách các số hàng bằng với số hàng trong E4. QUÁ có thể được dịch là "Lấy cho tôi một tập kết quả với thứ tự và phân vùng này và áp dụng (QUÁ) chức năng cửa sổ này cho tập kết quả đó độc lập với thứ tự trong câu lệnh CHỌN chính."

Thông tin thêm: Điều khoản QUÁ

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.