Làm thế nào tôi có thể GROUP BY
một cột, trong khi sắp xếp chỉ bằng một cột khác.
Tôi đang cố gắng làm như sau:
SELECT dbId,retreivalTime
FROM FileItems
WHERE sourceSite='something'
GROUP BY seriesName
ORDER BY retreivalTime DESC
LIMIT 100
OFFSET 0;
Tôi muốn chọn cuối cùng / n / mục từ FileItems, theo thứ tự giảm dần, với các hàng được lọc theo DISTINCT
các giá trị của seriesName
. Các lỗi truy vấn trên ERROR: column "fileitems.dbid" must appear in the GROUP BY clause or be used in an aggregate function
. Tôi cần dbid
giá trị để sau đó lấy đầu ra của truy vấn này và JOIN
nó trên bảng nguồn để lấy phần còn lại của các cột mà tôi đã chọn.
Lưu ý rằng về cơ bản đây là dấu hiệu của câu hỏi dưới đây, với rất nhiều chi tiết không liên quan được loại bỏ cho rõ ràng.
Câu hỏi gốc
Tôi có một hệ thống tôi đang chuyển từ sqlite3 sang PostgreSQL, vì tôi đã vượt xa sqlite:
SELECT
d.dbId,
d.dlState,
d.sourceSite,
[snip a bunch of rows]
d.note
FROM FileItems AS d
JOIN
( SELECT dbId
FROM FileItems
WHERE sourceSite='{something}'
GROUP BY seriesName
ORDER BY MAX(retreivalTime) DESC
LIMIT 100
OFFSET 0
) AS di
ON di.dbId = d.dbId
ORDER BY d.retreivalTime DESC;
Về cơ bản, tôi muốn chọn n mục cuối cùngDISTINCT
trong cơ sở dữ liệu, trong đó ràng buộc riêng biệt nằm trên một cột và thứ tự sắp xếp nằm trên một cột khác.
Thật không may, truy vấn trên, trong khi nó hoạt động tốt trong sqlite, lỗi trong PostgreQuery với lỗi psycopg2.ProgrammingError: column "fileitems.dbid" must appear in the GROUP BY clause or be used in an aggregate function
.
Thật không may, trong khi thêm dbId
vào mệnh đề GROUP BY khắc phục sự cố (ví dụ GROUP BY seriesName,dbId
), điều đó có nghĩa là bộ lọc riêng biệt trên kết quả truy vấn không còn hoạt động, vì dbid
là khóa chính của cơ sở dữ liệu và vì vậy tất cả các giá trị đều khác biệt.
Từ việc đọc tài liệu Postgres , có SELECT DISTINCT ON ({nnn})
, nhưng điều đó đòi hỏi các kết quả trả về phải được sắp xếp theo {nnn}
.
Vì vậy, để làm những gì tôi muốn qua SELECT DISTINCT ON
, tôi sẽ phải truy vấn cho tất cả DISTINCT {nnn}
và họ MAX(retreivalTime)
, sắp xếp lại bằng cách retreivalTime
thay sau đó {nnn}
, sau đó lấy lớn nhất 100 và truy vấn sử dụng những chống lại bảng để có được phần còn lại của các hàng, mà tôi Tôi muốn tránh, vì cơ sở dữ liệu có ~ 175K hàng và ~ 14K giá trị riêng biệt trong seriesName
cột, tôi chỉ muốn 100 mới nhất và truy vấn này có phần quan trọng về hiệu suất (tôi cần thời gian truy vấn <1/2 giây).
Giả định ngây thơ của tôi ở đây về cơ bản là DB cần lặp lại theo từng hàng theo thứ tự giảm dần retreivalTime
và chỉ dừng lại một khi nó nhìn thấy LIMIT
các mục, vì vậy một truy vấn bảng đầy đủ là không lý tưởng, nhưng tôi không giả vờ hiểu cơ sở dữ liệu như thế nào hệ thống tối ưu hóa trong nội bộ, và tôi có thể đang tiếp cận điều này hoàn toàn sai.
FWIW, đôi khi tôi sử dụng các OFFSET
giá trị khác nhau , nhưng thời gian truy vấn dài cho các trường hợp có độ lệch> ~ 500 là hoàn toàn chấp nhận được. Về cơ bản, OFFSET
là một cơ chế phân trang xảo quyệt cho phép tôi thoát ra mà không cần phải dành các con trỏ cuộn cho mỗi kết nối, và có lẽ tôi sẽ xem lại nó vào một lúc nào đó.
Tham khảo - Câu hỏi tôi đã hỏi một tháng trước dẫn đến truy vấn này .
Ok, ghi chú thêm:
SELECT
d.dbId,
d.dlState,
d.sourceSite,
[snip a bunch of rows]
d.note
FROM FileItems AS d
JOIN
( SELECT seriesName, MAX(retreivalTime) AS max_retreivalTime
FROM FileItems
WHERE sourceSite='{something}'
GROUP BY seriesName
ORDER BY max_retreivalTime DESC
LIMIT %s
OFFSET %s
) AS di
ON di.seriesName = d.seriesName AND di.max_retreivalTime = d.retreivalTime
ORDER BY d.retreivalTime DESC;
Hoạt động chính xác cho truy vấn như mô tả, nhưng nếu tôi loại bỏ các GROUP BY
điều khoản, nó không thành công (đó là tùy chọn trong ứng dụng của tôi).
psycopg2.ProgrammingError: column "FileItems.seriesname" must appear in the GROUP BY clause or be used in an aggregate function
Tôi nghĩ rằng về cơ bản tôi không hiểu cách thức các truy vấn con hoạt động trong PostgreSQL. Tôi làm sai ở đâu? Tôi có ấn tượng rằng một truy vấn con về cơ bản chỉ là một hàm nội tuyến, trong đó các kết quả chỉ được đưa vào truy vấn chính.