Tôi quay lại và trả lời câu hỏi này và câu trả lời. Rất tiếc, có một số trường hợp khi di chuyển bằng cách sử dụng "chức năng cửa sổ để xếp hạng" trở nên rất phức tạp. Những tình huống này là:
- nhiều công trình xây dựng KEEP-DENSE_RANK ở phần chọn của Oracle truy vấn dựa trên đơn đặt hàng khác nhau
- nhóm bằng cách nhóm các bộ/rollups
Vì vậy, tôi sẽ thêm vào câu trả lời thêm thông tin. SQLFIDDLE dữ liệu gốc: http://sqlfiddle.com/#!6/e5c6d/6
1. Reading oracle chức năng:
select max(m.id), m.someId keep (DENSE_RANK FIRST ORDER BY m.UpdateDate desc)
from MyTable m
groupBy m.someId
đó chúng tôi chọn tối đa của m.id trong nhóm (someId, UpdateDate), nơi UpdateDate là lớn nhất đó nhóm (someId)
2. thẳng về phía trước cách không hoạt động vì lỗi: Cột 'MyTable.UpdateDate' không hợp lệ trong các lựa chọn liệt kê vì nó không được chứa trong hàm tổng hợp hoặc mệnh đề GROUP BY.
SELECT FIRST_VALUE(id) OVER(PARTITION BY someId ORDER BY UpdateDate DESC, id DESC) first_in_orderedset , someId
FROM MyTable
GROUP BY someId
3. improoved 'thẳng về phía trước' là noneffective
SELECT someId, MIN(first_in_orderedset)
FROM
(SELECT FIRST_VALUE(id) OVER(PARTITION BY someId ORDER BY UpdateDate DESC, id DESC) first_in_orderedset , someId
FROM MyTable) t
GROUP BY someId;
4. chéo áp dụng:
SELECT grouped.someId, orderedSet.FirstUpdateDate, maxInSet.first_in_orderedset FROM
(
SELECT mt.someId
FROM MyTable mt
GROUP BY mt.someId
) grouped CROSS APPLY
(
SELECT top 1 mt2.UpdateDate as FirstUpdateDate
FROM MyTable mt2
WHERE mt2.someId=grouped.someId
ORDER BY UpdateDate desc
) orderedSet CROSS APPLY
(
SELECT max(mt3.id) as first_in_orderedset
FROM MyTable mt3
WHERE mt3.someId=grouped.someId and mt3.UpdateDate=orderedSet.FirstUpdateDate
) maxInSet;
5. Bây giờ cho phép có được bảng phức tạp hơn và truy vấn phức tạp hơn: ORACLE: http://sqlfiddle.com/#!4/c943c/23 SQL SERVER: http://sqlfiddle.com/#!6/dc7fb/1/0 (dữ liệu được pregenerated và nó là như nhau trong cả hai Hố cát - nó rất dễ dàng để so sánh kết quả) Bảng:
CREATE TABLE AlarmReports (
id int PRIMARY KEY,
clientId int, businessAreaId int , projectId int, taskId int,
process1Spent int, process1Lag int, process1AlarmRate varchar2(1) null,
process2Spent int, process2Lag int, process2AlarmRate varchar2(1) null,
process3Spent int, process3Lag int, process3AlarmRate varchar2(1) null
)
Oracle truy vấn:
SELECT clientId, businessAreaId, projectId,
sum(process1Spent),
sum(process2Spent),
sum(process3Spent),
MIN(process1AlarmRate) KEEP (DENSE_RANK FIRST ORDER BY process1Lag DESC),
MIN(process2AlarmRate) KEEP (DENSE_RANK FIRST ORDER BY process2Lag DESC),
MIN(process3AlarmRate) KEEP (DENSE_RANK FIRST ORDER BY process3Lag DESC)
FROM AlarmReports
GROUP BY GROUPING SETS ((),(clientId),(clientId, projectId),(businessAreaId),(clientId,businessAreaId))
truy vấn SQL:
(to be continued)
thực sự ở đó tôi đã lên kế hoạch để đưa tổng hợp tùy chỉnh của tôi wroted với C#. nếu ai đó quan tâm, xin vui lòng liên hệ với tôi ... tổng hợp tùy chỉnh là giải pháp tốt nhất của vấn đề như vậy nhưng nó không phải là unviersal về độ dài varchar. cho mỗi chiều dài varchar, bạn sẽ có nghĩa vụ tạo ra chức năng aggreate "chuyên biệt"
tôi không nhận được nó .. làm thế nào nó phải làm việc mà không có 'nhóm bởi someId'? Truy vấn của tôi sẽ luôn trả lại cho tôi 3 mục khi tôi có 3 phần tử khác nhau trong bảng. Truy vấn của bạn sẽ trả lại kết quả không phụ thuộc vào số lượng các phần tử khác nhau, do đó, nó sẽ là sai sau đó? – javagirl
@javagirl - Bạn đã thử nó trước chưa ?, nó sẽ hoạt động. Về cách thức hoạt động, các hàm phân tích ('OVER() ...') có thể có 'PARTITION BY' và không cần nhóm trên toàn bộ cấp độ. Nó trả về một giá trị cho mỗi hàng nằm trên bàn. – Lamak
Tôi đã đọc sai dữ liệu gốc. Vấn đề được cố định bằng cách đặt someid vào phân vùng thay vì id. –