Thứ tự MySQL theo nhóm trước


243

Có rất nhiều câu hỏi tương tự được tìm thấy ở đây nhưng tôi không nghĩ rằng bất kỳ câu trả lời nào cho câu hỏi đầy đủ.

Tôi sẽ tiếp tục từ câu hỏi phổ biến nhất hiện nay và sử dụng ví dụ của họ nếu điều đó ổn.

Nhiệm vụ trong trường hợp này là lấy bài đăng mới nhất cho mỗi tác giả trong cơ sở dữ liệu.

Truy vấn mẫu tạo ra kết quả không sử dụng được vì nó không phải luôn luôn là bài đăng mới nhất được trả về.

SELECT wp_posts.* FROM wp_posts
    WHERE wp_posts.post_status='publish'
    AND wp_posts.post_type='post'
    GROUP BY wp_posts.post_author           
    ORDER BY wp_posts.post_date DESC

Câu trả lời được chấp nhận hiện tại là

SELECT
    wp_posts.*
FROM wp_posts
WHERE
    wp_posts.post_status='publish'
    AND wp_posts.post_type='post'
GROUP BY wp_posts.post_author
HAVING wp_posts.post_date = MAX(wp_posts.post_date) <- ONLY THE LAST POST FOR EACH AUTHOR
ORDER BY wp_posts.post_date DESC

Thật không may, câu trả lời này là đơn giản và sai đơn giản và trong nhiều trường hợp tạo ra kết quả kém ổn định hơn so với truy vấn ban đầu.

Giải pháp tốt nhất của tôi là sử dụng một truy vấn con của mẫu

SELECT wp_posts.* FROM 
(
    SELECT * 
    FROM wp_posts
    ORDER BY wp_posts.post_date DESC
) AS wp_posts
WHERE wp_posts.post_status='publish'
AND wp_posts.post_type='post'
GROUP BY wp_posts.post_author 

Câu hỏi của tôi là một câu hỏi đơn giản sau đó: Có cách nào để đặt hàng trước khi nhóm mà không dùng đến một truy vấn con không?

Chỉnh sửa : Câu hỏi này là sự tiếp nối từ một câu hỏi khác và chi tiết cụ thể về tình huống của tôi hơi khác nhau. Bạn có thể (và nên) cho rằng đó cũng là một wp_posts.id là một định danh duy nhất cho bài đăng cụ thể đó.


2
Như bạn đã đề cập trong các nhận xét cho các câu trả lời đã cho, có thể có một số bài đăng có cùng Dấu thời gian. Nếu vậy, xin vui lòng cho một ví dụ với dữ liệu và kết quả mong đợi. Và hãy mô tả, tại sao bạn mong đợi kết quả này. post_authorpost_datekhông đủ để có được một hàng duy nhất, vì vậy cần phải có nhiều hơn để có một hàng duy nhất cho mỗipost_author
Ngài Rufo

@SirRufo Bạn nói đúng, tôi đã thêm một bản chỉnh sửa cho bạn.
Rob Forrest

There are plenty of similar questions to be found on here but I don't think that any answer the question adequately.Đó là những gì tiền thưởng dành cho.
Các cuộc đua nhẹ nhàng trong quỹ đạo

@LightnessRacesinOrbit, nếu câu hỏi hiện tại đã có câu trả lời được chấp nhận rằng theo tôi là sai, bạn sẽ đề nghị làm gì?
Rob Forrest

1
Tự hỏi tại sao bạn chấp nhận một câu trả lời sử dụng truy vấn con - khi câu hỏi của bạn hỏi rõ ràng ... "" Có cách nào để đặt hàng trước khi nhóm mà không dùng đến truy vấn phụ không? "???
TV-C-15

Câu trả lời:


373

Sử dụng ORDER BYmột truy vấn con không phải là giải pháp tốt nhất cho vấn đề này.

Giải pháp tốt nhất để có được max(post_date)tác giả là sử dụng truy vấn con để trả về ngày tối đa và sau đó nối nó vào bảng của bạn vào cả ngày post_authorvà ngày tối đa.

Giải pháp nên là:

SELECT p1.* 
FROM wp_posts p1
INNER JOIN
(
    SELECT max(post_date) MaxPostDate, post_author
    FROM wp_posts
    WHERE post_status='publish'
       AND post_type='post'
    GROUP BY post_author
) p2
  ON p1.post_author = p2.post_author
  AND p1.post_date = p2.MaxPostDate
WHERE p1.post_status='publish'
  AND p1.post_type='post'
order by p1.post_date desc

Nếu bạn có dữ liệu mẫu sau:

CREATE TABLE wp_posts
    (`id` int, `title` varchar(6), `post_date` datetime, `post_author` varchar(3))
;

INSERT INTO wp_posts
    (`id`, `title`, `post_date`, `post_author`)
VALUES
    (1, 'Title1', '2013-01-01 00:00:00', 'Jim'),
    (2, 'Title2', '2013-02-01 00:00:00', 'Jim')
;

Truy vấn con sẽ trả về ngày tối đa và tác giả của:

MaxPostDate | Author
2/1/2013    | Jim

Sau đó, vì bạn đang tham gia trở lại bảng, trên cả hai giá trị, bạn sẽ trả lại đầy đủ chi tiết của bài đăng đó.

Xem SQL Fiddle với Demo .

Để mở rộng nhận xét của tôi về việc sử dụng truy vấn con để trả về chính xác dữ liệu này.

MySQL không buộc bạn vào GROUP BYmọi cột mà bạn đưa vào SELECTdanh sách. Kết quả là, nếu bạn chỉ có GROUP BYmột cột nhưng trả về tổng cộng 10 cột, không có gì đảm bảo rằng các giá trị cột khác thuộc về cột đó post_authorđược trả về. Nếu cột không nằm trong mộtGROUP BY MySQL, chọn giá trị nào sẽ được trả về.

Sử dụng truy vấn con với hàm tổng hợp sẽ đảm bảo rằng tác giả và bài đăng chính xác được trả lại mỗi lần.

Là một lưu ý phụ, trong khi MySQL cho phép bạn sử dụng ORDER BYmột truy vấn con và cho phép bạn áp dụng một GROUP BYkhông phải mọi cột trong SELECTdanh sách thì hành vi này không được phép trong các cơ sở dữ liệu khác bao gồm SQL Server.


4
Tôi thấy những gì bạn đã làm ở đó nhưng chỉ đơn giản là trả về ngày mà bài đăng gần đây nhất được thực hiện, không phải toàn bộ hàng cho bài đăng gần đây nhất đó.
Rob Forrest

1
@RobForrest đó là những gì tham gia. Bạn trả lại ngày đăng gần đây nhất trong truy vấn con của tác giả và sau đó tham gia lại wp_postsvào cả hai cột của bạn để có được hàng đầy đủ.
Taryn

7
@RobForrest Đối với một, khi bạn áp dụng GROUP BYchỉ một cột, không có gì đảm bảo rằng các giá trị trong các cột khác sẽ luôn chính xác. Thật không may, MySQL cho phép loại CHỌN / NHÓM này xảy ra các sản phẩm khác không. Thứ hai, cú pháp sử dụng ORDER BYmột truy vấn con trong khi được phép trong MySQL không được phép trong các sản phẩm cơ sở dữ liệu khác bao gồm SQL Server. Bạn nên sử dụng một giải pháp sẽ trả về kết quả phù hợp mỗi khi nó được thực thi.
Taryn

2
Đối với quy mô, các hợp chất INDEX(post_author, post_date)là quan trọng.
Rick James

1
@ jtc Bông63 Đúng, nhưng nếu bạn đặt post_idtruy vấn bên trong thì về mặt kỹ thuật bạn cũng nên nhóm theo nó, điều này rất có thể sẽ làm sai lệch kết quả của bạn.
Taryn

20

Giải pháp của bạn sử dụng phần mở rộng cho mệnh đề GROUP BY cho phép nhóm theo một số trường (trong trường hợp này, chỉ post_author):

GROUP BY wp_posts.post_author

và chọn các cột không kết hợp:

SELECT wp_posts.*

không được liệt kê trong nhóm theo mệnh đề hoặc không được sử dụng trong hàm tổng hợp (MIN, MAX, COUNT, v.v.).

Sử dụng đúng phần mở rộng cho mệnh đề GROUP BY

Điều này hữu ích khi tất cả các giá trị của các cột không tổng hợp đều bằng nhau cho mỗi hàng.

Ví dụ: giả sử bạn có một cái bàn GardensFlowers( namecủa khu vườn, flowermọc trong vườn):

INSERT INTO GardensFlowers VALUES
('Central Park',       'Magnolia'),
('Hyde Park',          'Tulip'),
('Gardens By The Bay', 'Peony'),
('Gardens By The Bay', 'Cherry Blossom');

và bạn muốn trích xuất tất cả những bông hoa mọc trong một khu vườn, nơi có nhiều hoa mọc lên. Sau đó, bạn phải sử dụng một truy vấn con, ví dụ bạn có thể sử dụng điều này:

SELECT GardensFlowers.*
FROM   GardensFlowers
WHERE  name IN (SELECT   name
                FROM     GardensFlowers
                GROUP BY name
                HAVING   COUNT(DISTINCT flower)>1);

Thay vào đó, nếu bạn cần trích xuất tất cả những bông hoa là hoa duy nhất trong vườn, bạn có thể thay đổi điều kiện HAVING thành HAVING COUNT(DISTINCT flower)=1, nhưng MySql cũng cho phép bạn sử dụng điều này:

SELECT   GardensFlowers.*
FROM     GardensFlowers
GROUP BY name
HAVING   COUNT(DISTINCT flower)=1;

không truy vấn con, không phải SQL chuẩn, nhưng đơn giản hơn.

Sử dụng không chính xác phần mở rộng cho mệnh đề GROUP BY

Nhưng điều gì xảy ra nếu bạn CHỌN các cột không tổng hợp không bằng nhau cho mỗi hàng? Giá trị mà MySql chọn cho cột đó là gì?

Có vẻ như MySql luôn chọn FIRST giá trị mà nó gặp phải.

Để đảm bảo rằng giá trị đầu tiên mà nó gặp phải chính xác là giá trị bạn muốn, bạn cần áp dụng một GROUP BYtruy vấn theo thứ tự, do đó cần phải sử dụng truy vấn con. Bạn không thể làm điều đó khác.

Giả định rằng MySql luôn chọn hàng đầu tiên mà nó gặp, bạn đang sắp xếp chính xác các hàng trước NHÓM THEO. Nhưng thật không may, nếu bạn đọc tài liệu cẩn thận, bạn sẽ nhận thấy rằng giả định này không đúng.

Khi chọn các cột không tổng hợp không phải lúc nào cũng giống nhau, MySql có thể tự do chọn bất kỳ giá trị nào, vì vậy giá trị kết quả mà nó thực sự hiển thị là không xác định .

Tôi thấy rằng thủ thuật này để có được giá trị đầu tiên của một cột không tổng hợp được sử dụng rất nhiều và nó thường / hầu như luôn hoạt động, đôi khi tôi cũng sử dụng nó (có nguy cơ của riêng tôi). Nhưng vì nó không được ghi lại, bạn không thể dựa vào hành vi này.

Liên kết này (cảm ơn ypercube!) Thủ thuật GROUP BY đã được tối ưu hóa cho thấy một tình huống trong đó cùng một truy vấn trả về các kết quả khác nhau giữa MySql và MariaDB, có thể là do một công cụ tối ưu hóa khác nhau.

Vì vậy, nếu thủ thuật này hoạt động, đó chỉ là vấn đề may mắn.

Các câu trả lời được chấp nhận về vấn đề khác trông không đúng với tôi:

HAVING wp_posts.post_date = MAX(wp_posts.post_date)

wp_posts.post_datelà một cột không tổng hợp và giá trị của nó sẽ chính thức không được xác định, nhưng nó có thể sẽ là lần đầu tiên post_dategặp phải. Nhưng vì thủ thuật GROUP BY được áp dụng cho một bảng không có thứ tự, nên không chắc cái nào là đầu tiênpost_date gặp phải.

Nó có thể sẽ trả về các bài đăng là bài viết duy nhất của một tác giả, nhưng ngay cả điều này không phải lúc nào cũng chắc chắn.

Một giải pháp khả thi

Tôi nghĩ rằng đây có thể là một giải pháp khả thi:

SELECT wp_posts.*
FROM   wp_posts
WHERE  id IN (
  SELECT max(id)
  FROM wp_posts
  WHERE (post_author, post_date) = (
    SELECT   post_author, max(post_date)
    FROM     wp_posts
    WHERE    wp_posts.post_status='publish'
             AND wp_posts.post_type='post'
    GROUP BY post_author
  ) AND wp_posts.post_status='publish'
    AND wp_posts.post_type='post'
  GROUP BY post_author
)

Trên truy vấn bên trong, tôi sẽ trả lại ngày đăng tối đa cho mỗi tác giả. Sau đó, tôi đang xem xét thực tế rằng cùng một tác giả về mặt lý thuyết có thể có hai bài đăng cùng một lúc, vì vậy tôi chỉ nhận được ID tối đa. Và sau đó tôi sẽ trả lại tất cả các hàng có ID tối đa đó. Nó có thể được thực hiện nhanh hơn bằng cách sử dụng các phép nối thay vì mệnh đề IN.

(Nếu bạn chắc chắn rằng IDnó chỉ tăng và nếu ID1 > ID2cũng có nghĩa là post_date1 > post_date2, thì truy vấn có thể được thực hiện đơn giản hơn nhiều, nhưng tôi không chắc liệu đây có phải là trường hợp không).


Đó extension to GROUP Bylà một đọc thú vị, cảm ơn vì điều đó.
Rob Forrest


Các cột không kết hợp trong các biểu thức được chọn với GROUP BY không còn hoạt động theo mặc định với MySQL 5.7: stackoverflow.com/questions 432115174 / . IMHO nào an toàn hơn nhiều và buộc một số người viết các truy vấn hiệu quả hơn.
rink.attguard.6

Không câu trả lời này sử dụng một truy vấn con? Không phải Poster gốc yêu cầu một giải pháp KHÔNG sử dụng truy vấn con sao?
TV-C-15

1
@ TV-C-15 vấn đề là với việc sử dụng truy vấn phụ, và tôi đang giải thích lý do tại sao việc sử dụng một truy vấn phụ sẽ không hiệu quả. Ngay cả những câu trả lời được chấp nhận sử dụng một subquery nhưng nó bắt đầu giải thích lý do tại sao resorting là một ý tưởng tồi ( Sử dụng một ORDER BY trong một subquery không phải là giải pháp tốt nhất cho vấn đề này )
fthiella

9

Những gì bạn sẽ đọc là khá hack, vì vậy đừng thử điều này ở nhà!

Trong SQL nói chung, câu trả lời cho câu hỏi của bạn là KHÔNG , nhưng do chế độ thoải mái của GROUP BY(được đề cập bởi @bluefeet ), câu trả lời là trong MySQL.

Giả sử, bạn có một chỉ số BTREE trên (post_status, post_type, post_ Tác giả, post_date). Làm thế nào để chỉ số trông như dưới mui xe?

(post_status = 'Publish', post_type = 'post', post_ Author = 'user A', post_date = '2012-12-01') (post_status = 'Publish', post_type = 'post', post_ mượt = 'user A', post_date = '2012-12-31') (post_status = 'Publish', post_type = 'post', post_ Author = 'user B', post_date = '2012-10-01') (post_status = 'Publish', post_type = ' bài đăng ', post_ Tác giả =' người dùng B ', post_date =' 2012-12-01 ')

Đó là dữ liệu được sắp xếp theo tất cả các trường theo thứ tự tăng dần.

Khi bạn đang làm GROUP BYtheo mặc định, nó sắp xếp dữ liệu theo trường nhóm ( post_authortrong trường hợp của chúng tôi; post_status, post_type được yêu cầu bởiWHERE mệnh đề) và nếu có một chỉ mục phù hợp, nó sẽ lấy dữ liệu cho mỗi bản ghi đầu tiên theo thứ tự tăng dần. Đó là truy vấn sẽ tìm nạp sau đây (bài đăng đầu tiên cho mỗi người dùng):

(post_status = 'Publish', post_type = 'post', post_ Author = 'user A', post_date = '2012-12-01') (post_status = 'Publish', post_type = 'post', post_ mượt = 'user B', post_date = '2012-10-01')

Nhưng GROUP BYtrong MySQL cho phép bạn xác định thứ tự một cách rõ ràng. Và khi bạn yêu cầu post_usertheo thứ tự giảm dần, nó sẽ đi qua chỉ mục của chúng tôi theo thứ tự ngược lại, vẫn lấy bản ghi đầu tiên cho mỗi nhóm thực sự là cuối cùng.

Đó là

...
WHERE wp_posts.post_status='publish' AND wp_posts.post_type='post'
GROUP BY wp_posts.post_author DESC

sẽ cho chúng tôi

(post_status = 'Publish', post_type = 'post', post_ Author = 'user B', post_date = '2012-12-01') (post_status = 'Publish', post_type = 'post', post_ mượt = 'user A', post_date = '2012-12-31')

Bây giờ, khi bạn đặt hàng kết quả của nhóm theo post_date, bạn sẽ có được dữ liệu bạn muốn.

SELECT wp_posts.*
FROM wp_posts
WHERE wp_posts.post_status='publish' AND wp_posts.post_type='post'
GROUP BY wp_posts.post_author DESC
ORDER BY wp_posts.post_date DESC;

Lưu ý :

Đây không phải là những gì tôi muốn giới thiệu cho truy vấn cụ thể này. Trong trường hợp này, tôi sẽ sử dụng một phiên bản sửa đổi một chút của những gì @bluefeet gợi ý. Nhưng kỹ thuật này có thể rất hữu ích. Hãy xem câu trả lời của tôi ở đây: Lấy bản ghi cuối cùng trong mỗi nhóm

Cạm bẫy : Nhược điểm của phương pháp này là

  • kết quả của truy vấn phụ thuộc vào chỉ mục, điều này trái với tinh thần của SQL (các chỉ mục chỉ nên tăng tốc truy vấn);
  • chỉ mục không biết gì về ảnh hưởng của nó đối với truy vấn (bạn hoặc người khác trong tương lai có thể thấy chỉ mục quá tiêu tốn tài nguyên và thay đổi bằng cách nào đó, phá vỡ kết quả truy vấn, không chỉ hiệu suất của truy vấn)
  • nếu bạn không hiểu cách truy vấn hoạt động, rất có thể bạn sẽ quên lời giải thích trong một tháng và truy vấn sẽ gây nhầm lẫn cho bạn và đồng nghiệp của bạn.

Ưu điểm là hiệu suất trong trường hợp khó. Trong trường hợp này, hiệu năng của truy vấn phải giống như trong truy vấn của @ bluefeet, vì lượng dữ liệu liên quan đến việc sắp xếp (tất cả dữ liệu được tải vào một bảng tạm thời và sau đó được sắp xếp; btw, truy vấn của anh ấy cũng yêu cầu (post_status, post_type, post_author, post_date)chỉ mục) .

Những gì tôi muốn đề nghị :

Như tôi đã nói, những truy vấn đó khiến MySQL lãng phí thời gian để sắp xếp lượng dữ liệu khổng lồ trong một bảng tạm thời. Trong trường hợp bạn cần phân trang (có liên quan đến GIỚI HẠN), hầu hết dữ liệu thậm chí còn bị loại bỏ. Những gì tôi sẽ làm là giảm thiểu lượng dữ liệu được sắp xếp: đó là sắp xếp và giới hạn tối thiểu dữ liệu trong truy vấn con và sau đó nối lại toàn bộ bảng.

SELECT * 
FROM wp_posts
INNER JOIN
(
  SELECT max(post_date) post_date, post_author
  FROM wp_posts
  WHERE post_status='publish' AND post_type='post'
  GROUP BY post_author
  ORDER BY post_date DESC
  -- LIMIT GOES HERE
) p2 USING (post_author, post_date)
WHERE post_status='publish' AND post_type='post';

Truy vấn tương tự sử dụng cách tiếp cận được mô tả ở trên:

SELECT *
FROM (
  SELECT post_id
  FROM wp_posts
  WHERE post_status='publish' AND post_type='post'
  GROUP BY post_author DESC
  ORDER BY post_date DESC
  -- LIMIT GOES HERE
) as ids
JOIN wp_posts USING (post_id);

Tất cả những truy vấn với kế hoạch thực hiện của họ trên SQLFiddle .


Đó là một kỹ thuật thú vị mà bạn đã có ở đó. Hai điều: bạn nói đừng thử điều này ở nhà, những cạm bẫy tiềm ẩn là gì? Thứ hai, bạn đề cập đến một phiên bản sửa đổi một chút của câu trả lời của bluefeet, đó sẽ là gì?
Rob Forrest

Cảm ơn vì điều đó, thật thú vị khi thấy ai đó tấn công vấn đề theo một cách khác. Vì tập dữ liệu của tôi không ở gần hàng 18M + của bạn, tôi không nghĩ hiệu suất cũng quan trọng như khả năng duy trì nên tôi nghĩ các tùy chọn sau này của bạn có thể phù hợp hơn. Tôi thích ý tưởng về giới hạn bên trong của truy vấn con.
Rob Forrest

8

Hãy thử cái này Chỉ cần lấy danh sách ngày đăng bài mới nhất từ ​​mỗi tác giả . Đó là nó

SELECT wp_posts.* FROM wp_posts WHERE wp_posts.post_status='publish'
AND wp_posts.post_type='post' AND wp_posts.post_date IN(SELECT MAX(wp_posts.post_date) FROM wp_posts GROUP BY wp_posts.post_author) 

@Rob Forrest, kiểm tra giải pháp của tôi. Nó giải quyết câu hỏi của bạn, hy vọng!
sanchitkhanna26

1
Tôi xin lỗi, tôi không nghĩ rằng nó sẽ làm việc. Ví dụ: nếu cả tác giả 1 và tác giả 2 đều xuất bản một cái gì đó vào ngày 01/02/13 và sau đó tác giả 2 đăng một cái gì đó mới vào ngày 08/02/13, cả 3 bài viết sẽ được trả lại. Có, trường datetime bao gồm thời gian nên tình huống ít xảy ra hơn nhưng không có nghĩa là nó được đảm bảo trên một tập dữ liệu đủ lớn.
Rob Forrest

+1 để sử dụng post_date IN (select max(...) ...). Điều này hiệu quả hơn so với thực hiện một nhóm bằng cách chọn phụ, xem dev.mysql.com/doc/refman/5.6/en/subquery-optimization.html
Seaux

chỉ cần làm rõ, điều đó chỉ tối ưu hơn nếu bạn đã lập chỉ mục post_ Tác giả.
Seaux

1
IN ( SELECT ... )ít hiệu quả hơn nhiều so với THAM GIA tương đương.
Rick James

3

Không có ý nghĩa gì khi đặt hàng các bản ghi trước khi nhóm, vì việc phân nhóm sẽ làm thay đổi tập kết quả. Cách truy vấn phụ là cách ưa thích. Nếu việc này diễn ra quá chậm, bạn sẽ phải thay đổi thiết kế bảng của mình, ví dụ: bằng cách lưu trữ id của bài đăng cuối cùng cho mỗi tác giả trong một bảng riêng biệt hoặc giới thiệu một cột boolean cho mỗi tác giả bài đăng của mình là bài cuối cùng một.


Dennish, bạn sẽ trả lời các bình luận của Bluefeet như thế nào rằng loại truy vấn này không đúng cú pháp SQL và do đó không thể di chuyển trên các nền tảng cơ sở dữ liệu? Cũng có những lo ngại rằng không có gì đảm bảo rằng điều này sẽ tạo ra kết quả chính xác mỗi lần.
Rob Forrest

2

Chỉ cần sử dụng chức năng tối đa và chức năng nhóm

    select max(taskhistory.id) as id from taskhistory
            group by taskhistory.taskid
            order by taskhistory.datum desc

3
Điều gì xảy ra nếu cái có id cao nhất không được đăng gần đây nhất? Một ví dụ về điều này có thể là tác giả đã giữ bài viết của mình trong bản thảo trong một thời gian dài trước khi đăng nó.
Rob Forrest

0

Chỉ cần tóm tắt lại, giải pháp tiêu chuẩn sử dụng một truy vấn con không tương thích và trông như thế này:

SELECT x.*
  FROM my_table x
  JOIN (SELECT grouping_criteria,MAX(ranking_criterion) max_n FROM my_table GROUP BY grouping_criteria) y
    ON y.grouping_criteria = x.grouping_criteria
   AND y.max_n = x.ranking_criterion;

Nếu bạn đang sử dụng phiên bản cổ của MySQL hoặc tập dữ liệu khá nhỏ, thì bạn có thể sử dụng phương pháp sau:

SELECT x.*
  FROM my_table x
  LEFT
  JOIN my_table y
    ON y.joining_criteria = x.joining_criteria
   AND y.ranking_criteria < x.ranking_criteria
 WHERE y.some_non_null_column IS NULL;  

Khi bạn nói phiên bản cổ, phiên bản nào của MySQL này sẽ chạy trên? Và xin lỗi không, tập dữ liệu khá lớn trong ví dụ của tôi.
Rob Forrest

Nó sẽ hoạt động (từ từ) trên bất kỳ phiên bản nào. Các phiên bản cũ hơn không thể sử dụng các truy vấn con.
Dâu

Đúng, phương pháp # 2 (phiên bản tôi đã thử là từ đây ) sẽ không hoạt động trên một tập dữ liệu lớn (hàng triệu hàng), gây ra lỗi kết nối bị mất . Phương pháp # 1 mất ~ 15 giây để thực hiện truy vấn. Ban đầu tôi muốn tránh sử dụng các truy vấn lồng nhau, nhưng điều này khiến tôi phải xem xét lại. Cảm ơn bạn!
aexl

@TheottiestManinJamaica Vâng. Không có nhiều thay đổi trong 3,5 năm. Giả sử một truy vấn tự nó hiệu quả, thì thời gian mà truy vấn cần thực hiện phần lớn phụ thuộc vào kích thước của tập dữ liệu, sự sắp xếp các chỉ mục và phần cứng có sẵn.
Dâu

-1

** Các truy vấn phụ có thể có tác động xấu đến hiệu suất khi được sử dụng với các bộ dữ liệu lớn **

Truy vấn gốc

SELECT wp_posts.*
FROM   wp_posts
WHERE  wp_posts.post_status = 'publish'
       AND wp_posts.post_type = 'post'
GROUP  BY wp_posts.post_author
ORDER  BY wp_posts.post_date DESC; 

Truy vấn đã sửa đổi

SELECT p.post_status,
       p.post_type,
       Max(p.post_date),
       p.post_author
FROM   wp_posts P
WHERE  p.post_status = "publish"
       AND p.post_type = "post"
GROUP  BY p.post_author
ORDER  BY p.post_date; 

bởi vì tôi đang sử dụng maxtrong select clause==> max(p.post_date)có thể tránh các truy vấn chọn phụ và sắp xếp theo cột tối đa sau nhóm theo.


1
Điều này thực sự trả về post_date gần đây nhất cho mỗi tác giả nhưng không có gì đảm bảo rằng phần còn lại của dữ liệu được trả về liên quan đến bài đăng có post_date gần đây nhất.
Rob Forrest

@RobForrest -> Tôi không hiểu tại sao? đó là một ý tưởng tốt để xây dựng câu trả lời của bạn và chỉ cần đưa ra yêu cầu. Theo như tôi hiểu thì dữ liệu được đảm bảo có liên quan khi tôi sử dụng mệnh đề where để lọc dữ liệu liên quan.
Guykaplan

1
Ở một mức độ nào đó, bạn hoàn toàn chính xác, mỗi trong số 4 trường bạn đang chọn sẽ liên quan đến post_date tối đa đó, nhưng điều này không trả lời câu hỏi đã được hỏi. Ví dụ: nếu bạn đã thêm post_id hoặc nội dung của bài đăng thì các cột đó sẽ không được đảm bảo là từ cùng một bản ghi với ngày tối đa. Để có được truy vấn của bạn ở trên để trả về phần còn lại của chi tiết của bài đăng, bạn sẽ phải chạy truy vấn thứ hai. Nếu câu hỏi là về việc tìm ngày của bài đăng gần đây nhất, thì có, câu trả lời của bạn sẽ ổn.
Rob Forrest

@guykaplan, Truy vấn con không chậm. Kích thước của tập dữ liệu không thành vấn đề. Nó phụ thuộc vào cách bạn sử dụng nó. Xem percona.com/blog/2010/03/18/when-the-subelect-runs-faster
Pacerier

@Pacerier: bài viết thực sự cho thấy cách bạn có thể nhận được lợi ích hiệu suất từ ​​các truy vấn phụ, nhưng tôi rất thích thấy bạn chuyển đổi kịch bản đã cho để thực hiện tốt hơn. và Kích thước dữ liệu rất quan trọng, một lần nữa trong bài viết đã cho mà bạn đăng, bạn cho rằng chỉ có một bảng để làm việc. kích thước dữ liệu không phải bởi kích thước hàng, là bởi kích thước phức tạp. có nói rằng, nếu bạn đang làm việc với bảng thực sự lớn (không có nhiều bảng liên quan) truy vấn phụ có thể thực hiện tốt hơn nhiều.
Guykaplan

-4

Đầu tiên, không sử dụng * trong select, ảnh hưởng đến hiệu suất của chúng và cản trở việc sử dụng nhóm theo thứ tự. Hãy thử truy vấn này:

SELECT wp_posts.post_author, wp_posts.post_date as pdate FROM wp_posts
WHERE wp_posts.post_status='publish'
AND wp_posts.post_type='post'
GROUP BY wp_posts.post_author           
ORDER BY pdate DESC

Khi bạn không chỉ định bảng trong ORDER BY, chỉ cần bí danh, họ sẽ sắp xếp kết quả của lựa chọn.


Bỏ qua các lựa chọn *, chúng sẽ cho ngắn gọn trong ví dụ này. Câu trả lời của bạn giống hệt như ví dụ đầu tiên tôi đưa ra.
Rob Forrest

Bí danh không ảnh hưởng đến hàng nào được trả về cũng như sắp xếp kết quả.
Rob Forrest
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.