2014-06-05 14 views
5

Có cách nào để nhóm theo khóa duy nhất (chính), về cơ bản, đảm bảo rằng các cột khác từ bảng đó sẽ được xác định rõ ràng?GROUP BY chỉ có khóa chính, nhưng chọn các giá trị khác

SELECT myPrimaryKey, otherThing 
FROM myTable 
GROUP BY myPrimaryKey 

Tôi biết rằng tôi có thể thêm các cột khác vào câu lệnh (GROUP BY myPrimaryKey,otherThing), nhưng tôi đang cố gắng tránh điều đó. Nếu bạn tò mò tại sao, hãy đọc tiếp:


Tôi có một tuyên bố trong đó chủ yếu là làm điều này:

SELECT nodes.node_id, nodes.node_label, COUNT(1) 
FROM {a couple of joined tables} 
INNER JOIN nodes USING (node_id) 
GROUP BY nodes.node_id, nodes.node_label 

mà hoạt động tốt, nhưng là một chút chậm trong MySQL. Nếu tôi xóa nodes.node_label khỏi GROUP BY, nó chạy nhanh hơn khoảng 10 lần (theo EXPLAIN, điều này là do một trong các lần gia nhập trước đó bắt đầu sử dụng chỉ mục khi trước đó nó không).

Chúng tôi đang trong quá trình di chuyển sang Postgres, vì vậy tất cả các tuyên bố mới được cho là tương thích với cả MySQL Postgres khi có thể. Bây giờ trong Postgres, câu lệnh gốc chạy nhanh, nhưng câu lệnh mới (với nhóm bị giảm) sẽ không chạy (vì Postgres là chặt chẽ hơn). Trong trường hợp này, đó là một lỗi sai bởi vì câu lệnh thực sự được xác định rõ ràng.

Có cú pháp nào tôi có thể sử dụng để cho cùng một câu lệnh chạy trong cả hai nền tảng, trong khi cho phép MySQL chỉ sử dụng một cột trong nhóm bằng tốc độ?

+3

'Trong trường hợp này, đó là một lỗi sai vì báo cáo kết quả thực sự nổi defined.' Không không không, MySql chấp nhận weirds điều cho GROUP BY (với kết quả không thể đoán trước), tất cả các DBMS khác buộc bạn phải có được kết quả dự đoán (thường là hữu ích). Để tìm một giải pháp, tôi thà làm việc về quản lý chỉ mục, để tránh sự chậm trễ của MySql! –

+0

@ RaphaëlAlthaus thường là sự thật, nhưng nhóm theo khóa chính (hoặc bất kỳ khóa 'UNIQUE') nào đảm bảo rằng tất cả các giá trị khác trong cùng một bảng đều được xác định rõ. – Dave

+0

nhưng tôi nghi ngờ rằng đó là cách một dbms hoạt động. Tôi không nghĩ rằng truy vấn quét và phân tích cú pháp kiểm tra cho các khóa chính/khóa duy nhất. Điều đó xuất hiện sau (chiến lược tối ưu hóa truy vấn/thực hiện) ... –

Trả lời

0

Bạn có thể thử chuyển đổi các cột khác vào uẩn:

SELECT myPrimaryKey, MAX(otherThing) 
FROM myTable 
GROUP BY myPrimaryKey 
+0

Tôi thích mẹo này và tôi sẽ sử dụng nó ngay bây giờ. Nhưng như RichardHuxton đã chỉ ra, hành vi mà tôi đang tìm kiếm được cho phép trong Postgres 9.1+, vì vậy là một giải pháp lâu dài hơn, tôi sẽ yêu cầu để cập nhật cơ sở dữ liệu thử nghiệm. – Dave

+0

NHỮNG GÌ NÊN ĐƯỢC LÀM VIỆC, KHI TÔI CHỈ DỰ ÁN CHÍNH CHÍNH? –

1

Trong Postgres (không phải trong MySQL, mặc dù), bạn có thể sử dụng DISTINCT ON để chọn một đơn, hàng phù hợp cho mỗi giá trị (hoặc một nhóm giá trị) mà không tổng hợp chúng:

SELECT DISTINCT ON (n.node_id) 
     *     -- select any or all columns of all joined tables 
FROM {a couple of joined tables} 
JOIN nodes n USING (node_id) 

Cung cấp cho bạn một, hàng tùy ý duy nhất cho mỗi node_id. để chọn một hàng cụ thể, hãy thêm:

ORDER BY n.node_id, ... -- what to sort first? 

.. thêm nhiều hơn ORDER BY mục để chọn một hàng cụ thể. Thông tin chi tiết:
Select first row in each GROUP BY group?

0

Trong nhiều phiên bản gần đây của MySql bạn có thể có sql_mode=only_full_group_by kích hoạt mà không cho phép để chọn cột không tổng hợp khi sử dụng group by tức là nó buộc bạn phải sử dụng một chức năng như max() hoặc avg() hoặc group_concat(), đôi khi bạn chỉ muốn bất kỳ giá trị nào.

Cờ này được bật theo mặc định trong MySql 5.7.

Chức năng any_value() khả dụng khi cờ đó được bật.

Bạn có thể đạt được hiệu ứng tương tự mà không vô hiệu hóa ONLY_FULL_GROUP_BY bằng cách sử dụng ANY_VALUE() để tham chiếu đến cột không được phân tách.

select t.index, any_value(t.insert_date) 
from my_table t 
group by t.index; 

biết thêm thông tin ở đây: https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_only_full_group_by và ở đây: https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html

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