2012-03-29 72 views
5

Tôi cần một câu lệnh MySql sẽ chọn tất cả các hàng, cũng như tổng số hàng có.MySql chọn số hàng là cột phụ?

Tôi đã sử dụng

mysql_query("SELECT * FROM posts LIMIT 0, 5"); 

... cố gắng để thêm các tính:

mysql_query("SELECT *, COUNT(*) AS total FROM posts LIMIT 0, 5"); 

... nhưng đó chỉ trả về một hàng duy nhất.

Ngoài ra, nếu có cách tốt hơn để có tổng số hơn để thêm cột phụ vào mỗi hàng, thì tôi muốn thay thế. Cảm ơn bạn!

+2

Nếu bạn đang sử dụng PHP, tại sao không sử dụng 'mysql_num_rows' – hjpotter92

+1

@ hjpotter92 nhưng nó phụ thuộc vào" tổng "OP đang suy nghĩ. Tổng số hiện được chọn (hơn 'mysql_num_rows' là tốt) hoặc số hàng trong toàn bộ bảng. –

+0

Điểm tốt, @Michal. Tôi đã giải quyết cả hai trường hợp trong câu trả lời của tôi. –

Trả lời

9

Tôi cần một tuyên bố MySql rằng sẽ chọn tất cả các hàng, cũng như bao nhiêu hàng tổng có.

Khi được thực hiện theo nghĩa đen, điều này là không thể. Kết quả của một truy vấn SQL là một bảng (ảo); cột trong mỗi hàng trong bảng kết quả đó cung cấp một giá trị chỉ được liên kết với hàng đó và các hàng có hiệu lực độc lập với nhau.

Có nhiều cách để lấy số lượng hàng trong toàn bộ kết quả, nhưng được thực hiện trong hai câu lệnh hoặc với truy vấn khác với khái niệm của bạn. (Giải pháp dưới đây)

Có một khía cạnh trong câu hỏi ban đầu của bạn có thể được hiểu theo nhiều cách:

cũng như có bao nhiêu tổng hàng có

Điều này có nghĩa một trong hai:

  1. Đếm từng hàng được trả lại trong kết quả.
  2. Đếm mỗi hàng mà có thể đã được trả lại nếu nó không được cho LIMIT khoản (mà truncates kết quả đến 5 hàng trong trường hợp này)

(Tôi sẽ đưa ra câu trả lời cho cả hai bên dưới)

nhưng chỉ trả về một hàng. Tôi đoán đó là vì COUNT (*) sẽ giống nhau cho mỗi hàng, và vì một lý do nào đó, MySql chỉ trả về các hàng với các giá trị duy nhất cho nó? Tôi không có đầu mối.

COUNT là hàm tổng hợp. Bằng cách sử dụng hàm tổng hợp, bạn đang yêu cầu cơ sở dữ liệu gộp nhóm các hàng và chiếu một số khía cạnh của nó vào một hàng duy nhất. Điều gì là khó hiểu là mysql cũng bạn kết hợp các biểu thức không tổng hợp và tổng hợp trong cùng một danh sách SELECT. Hầu hết các cơ sở dữ liệu khác không cho phép điều này và cung cấp cho bạn một lỗi cho điều này, nhưng alas MySQL không.

Nhưng COUNT (*) vẫn tổng hợp tất cả các hàng thành một hàng, đại diện cho toàn bộ nhóm hàng.

Ngoài ra, nếu có cách tốt hơn để có tổng số hơn để thêm cột phụ vào mỗi hàng, thì tôi muốn thay thế. Cảm ơn bạn!

có, có một số cách.

Nếu bạn muốn lấy số hàng được trả về PHP, vì vậy, sau khi MySQL áp dụng điều khoản giới hạn, tôi đề nghị chỉ cần gọi hàm php mysql_num_rows (http://www.php.net/manual/en/function.mysql-num-rows.php) sau khi thực hiện cuộc gọi mysql_query.

Nếu bạn muốn nhận được số hàng có thể được trả lại khi không có mệnh đề LIMIT, tôi khuyên bạn nên thực hiện theo 2 bước: trước tiên, thực hiện phiên bản được sửa đổi chậm của truy vấn ban đầu, sau đó, đó, gọi hàm FOUND_ROWS của MySQL. (Xem http://dev.mysql.com/doc/refman/5.5/en/information-functions.html#function_found-rows)

Nó sẽ trông như thế này:

$result = mysql_query('SELECT SQL_CALC_FOUND_ROWS * FROM posts LIMIT 0, 5'); 
//do stuff with the result, but don't do any other queries 

//get the total number of rows (disregarding the LIMIT clause) 
$result = mysql_query('SELECT FOUND_ROWS()'); 

Các modifier SQL_CALC_FOUND_ROWS nói với MySQL để theo dõi tổng số hàng trước khi áp dụng mệnh đề LIMITFOUND_ROWS() lợi nhuận con số đó. Giữ 2 điều trong tâm trí:

  1. cả những mysql_query cuộc gọi phải được thực hiện qua kết nối cùng
  2. Đừng thực hiện một truy vấn Inbetween những cuộc gọi đến mysql_query

Oh, lưu ý cuối cùng: khi sử dụng LIMIT, bạn thường muốn kết quả được sắp xếp theo một cách cụ thể. Thông thường, mọi người sử dụng LIMIT để phân trang. Nếu bạn không đặt hàng, thứ tự không xác định và các truy vấn tiếp theo có thể trả lại các hàng đã được trả về bởi các câu lệnh trước, ngay cả khi bù đắp LIMIT là khác nhau. Bạn có thể đặt hàng một cách rõ ràng kết quả bằng cách sử dụng mệnh đề ORDER BY. (http://dev.mysql.com/doc/refman/5.5/en/select.html)

+0

Có, tôi đồng ý với bạn hoàn toàn về tuyên bố cuối cùng của bạn, nó thực sự có thể đặt kết quả một cách rõ ràng bằng cách sử dụng mệnh đề 'ORDER BY'. Trong thực tế, tôi thậm chí sẽ đi xa như để nói, "** chỉ ** bằng cách sử dụng một mệnh đề' ORDER BY' ". ;) Chỉ là một chút mỉa mai, xin lỗi. Tôi tìm câu trả lời của bạn cũng được xây dựng và giáo dục, +1. –

+1

+1 cho 'FOUND_ROWS()' –

+0

@Andriy heh, cảm ơn :) Chỉ cần một nitpick, nhưng trong MySQL, cho tốt hơn hoặc xấu hơn, một mệnh đề GROUP BY cũng được đảm bảo trả về một kết quả có trật tự. Bạn thậm chí có thể chỉ định các công cụ sửa đổi ASC và DESC cho các biểu thức trong danh sách GROUP BY. –

8

Tôi không chắc chắn về tổng số bạn đang nghĩ: tổng số hiện được chọn hoặc số lượng tất cả các hàng trong toàn bộ bảng. Này trả về số của tất cả các hàng trong toàn bộ bảng, tất nhiên trong từng cùng giá trị hàng:

mysql_query("SELECT *, (select COUNT(*) from posts) AS total FROM posts LIMIT 0, 5"); 
+0

Được rồi, cảm ơn, điều đó thật hoàn hảo. Tôi giả sử tôi chỉ có thể sửa đổi truy vấn khác để chọn số lượng những gì tôi muốn nó. Liệu điều này có hiệu quả khủng khiếp không? Nó có thực hiện gấp đôi số truy vấn không? – mowwwalker

+0

@Walkerneo Nếu đó là câu hỏi thực tế của bạn, thì mysql_num_rows là giải pháp tốt nhất. – hjpotter92

+0

@Walkerneo nó không tương quan (không có mối tương quan giữa truy vấn bên ngoài và bên trong) vì vậy nó không nên mất hiệu quả. Và có bạn có thể giới hạn truy vấn bên trong cho bất cứ điều gì bạn muốn. –

1

Tôi nghĩ rằng bạn đang quá phức tạp vấn đề này. Tôi không thấy có vấn đề với việc sử dụng hai truy vấn.

truy vấn đầu tiên để có được bài viết mỗi ngày (tôi giả sử bạn muốn tổng trong toàn bộ bảng):

SELECT COUNT(*) AS total FROM posts; 

Và một giây, để truy vấn cho bài viết của mình:

SELECT * FROM posts LIMIT 0, 5 

Các lý do là không phải lúc nào cũng là điều xấu để truy xuất dữ liệu bằng nhiều truy vấn, đặc biệt là khi có ý nghĩa.

Nếu bạn thêm cột này làm cột bổ sung bằng cách nói truy vấn phụ, bạn sẽ có tổng số trong mỗi hàng, nhưng về cơ bản bạn vẫn đang chạy hai truy vấn (hoặc truy vấn con chạy cho mỗi hàng, tôi không thể nhớ?)

Nó cũng cung cấp tính linh hoạt hơn để nhận số đầu tiên vì một số truy vấn sẽ trả về tổng số sai tùy thuộc vào mức độ phức tạp của truy vấn của bạn.Và bạn có thể cần phải sửa đổi truy vấn đếm để bạn có được tổng số chính xác và có thể phân trang chính xác.

Ví dụ: trong trường hợp truy vấn từ một đến nhiều, giả sử bạn muốn nhận bài đăng và nhận xét, bạn sẽ nhận được số lượng sai vì bài đăng sẽ bị trùng lặp cho mỗi nhận xét cho bài đăng đó.

viết tắt Ví dụ:

post_id | comment_id 
1  | 1 
1  | 2 
2  | 3 
3  | 4 
3  | 5 

Vì vậy, để làm điều đó một cách chính xác đầu tiên bạn cần để chạy các truy vấn sau đây để có được bài viết mỗi ngày:

SELECT COUNT(*) AS total FROM posts; 

Và sau đó bạn sẽ cần phải chạy:

SELECT id FROM posts limit 0, 5; 

Và cuối cùng bạn muốn chạy:

select p.id, c.id from posts p left join comments c on c.post_id = p.id where id in(id list from above query) 

Rõ ràng truy vấn của bạn sẽ không chạy vào vấn đề trên. Nhưng tôi chỉ đang cố gắng minh họa tại sao nó có thể là tốt để có được tổng số trong một truy vấn riêng biệt.

+1

Sử dụng nhiều truy vấn đòi hỏi phải suy nghĩ về đồng thời, mặc dù. Điều gì sẽ xảy ra nếu một thứ gì đó thêm hoặc xóa các hàng sau khi truy vấn đầu tiên của bạn kết thúc, nhưng trước khi truy vấn thứ hai bắt đầu? Số được trả về bởi truy vấn thứ hai sẽ không phù hợp với kết quả của lần truy vấn đầu tiên.(Bạn có thể tránh điều đó bằng cách thực hiện cả hai truy vấn trong một giao dịch đơn lẻ với mức cô lập đủ cao.) – Wyzard

+0

Có, điểm tốt về việc chạy các truy vấn trong một giao dịch. – Gohn67

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