Helpex - Trao đổi & giúp đỡ Đăng nhập
100

Có cách nào tôi có thể lấy số hàng thực từ một truy vấn không?

Tôi muốn có thể đặt một bảng được gọi là league_girl theo trường được gọi là điểm số; và trả lại tên người dùng và vị trí hàng thực của tên người dùng đó.

Tôi muốn xếp hạng người dùng để tôi có thể biết vị trí của một người dùng cụ thể. Joe ở vị trí 100 trên 200, tức là

User Score Row
Joe  100    1
Bob  50     2
Bill 10     3

Tôi đã thấy một vài giải pháp ở đây nhưng tôi đã thử hầu hết chúng và không có giải pháp nào trong số chúng thực sự trả lại số hàng.

Tôi đã thử điều này:

SELECT position, username, score
FROM (SELECT @row := @row + 1 AS position, username, score 
       FROM league_girl GROUP BY username ORDER BY score DESC) 

Như có nguồn gốc

... nhưng nó dường như không trả lại vị trí hàng.

Có ý kiến ​​gì không?

100 hữu ích 5 bình luận 142k xem chia sẻ
175

Bạn có thể muốn thử những cách sau:

SELECT  l.position, 
        l.username, 
        l.score,
        @curRow := @curRow + 1 AS row_number
FROM    league_girl l
JOIN    (SELECT @curRow := 0) r;

Phần JOIN (SELECT @curRow := 0)cho phép khởi tạo biến mà không yêu cầu một SETlệnh riêng biệt .

Trường hợp thử nghiệm:

CREATE TABLE league_girl (position int, username varchar(10), score int);
INSERT INTO league_girl VALUES (1, 'a', 10);
INSERT INTO league_girl VALUES (2, 'b', 25);
INSERT INTO league_girl VALUES (3, 'c', 75);
INSERT INTO league_girl VALUES (4, 'd', 25);
INSERT INTO league_girl VALUES (5, 'e', 55);
INSERT INTO league_girl VALUES (6, 'f', 80);
INSERT INTO league_girl VALUES (7, 'g', 15);

Truy vấn kiểm tra:

SELECT  l.position, 
        l.username, 
        l.score,
        @curRow := @curRow + 1 AS row_number
FROM    league_girl l
JOIN    (SELECT @curRow := 0) r
WHERE   l.score > 50;

Kết quả:

+----------+----------+-------+------------+
| position | username | score | row_number |
+----------+----------+-------+------------+
|        3 | c        |    75 |          1 |
|        5 | e        |    55 |          2 |
|        6 | f        |    80 |          3 |
+----------+----------+-------+------------+
3 rows in set (0.00 sec)
175 hữu ích 5 bình luận chia sẻ
38
SELECT @i:=@i+1 AS iterator, t.*
FROM tablename t,(SELECT @i:=0) foo
38 hữu ích 1 bình luận chia sẻ
7

Đây là cấu trúc của mẫu tôi đã sử dụng:

  select
          /*this is a row number counter*/
          ( select @rownum := @rownum + 1 from ( select @rownum := 0 ) d2 ) 
          as rownumber,
          d3.*
  from 
  ( select d1.* from table_name d1 ) d3

Và đây là mã làm việc của tôi:

select     
           ( select @rownum := @rownum + 1 from ( select @rownum := 0 ) d2 ) 
           as rownumber,
           d3.*
from
(   select     year( d1.date ), month( d1.date ), count( d1.id )
    from       maindatabase d1
    where      ( ( d1.date >= '2013-01-01' ) and ( d1.date <= '2014-12-31' ) )
    group by   YEAR( d1.date ), MONTH( d1.date ) ) d3
7 hữu ích 2 bình luận chia sẻ
4

Bạn cũng có thể dùng

SELECT @curRow := ifnull(@curRow,0) + 1 Row, ...

để khởi tạo biến đếm.

4 hữu ích 3 bình luận chia sẻ
3

Giả sử MySQL hỗ trợ nó, bạn có thể dễ dàng thực hiện việc này với một truy vấn con SQL chuẩn:

select 
    (count(*) from league_girl l1 where l2.score > l1.score and l1.id <> l2.id) as position,
    username,
    score
from league_girl l2
order by score;

Đối với số lượng lớn kết quả được hiển thị, điều này sẽ hơi chậm và thay vào đó bạn sẽ muốn chuyển sang tự tham gia.

3 hữu ích 0 bình luận chia sẻ
3

Nếu bạn chỉ muốn biết vị trí của một người dùng cụ thể sau khi sắp xếp theo điểm trường, bạn có thể chỉ cần chọn tất cả hàng từ bảng của mình nơi điểm trường cao hơn điểm người dùng hiện tại. Và sử dụng số hàng được trả về + 1 để biết vị trí của người dùng hiện tại này.

Giả sử rằng bảng của bạn là league_girlvà trường chính của bạn là id, bạn có thể sử dụng điều này:

SELECT count(id) + 1 as rank from league_girl where score > <your_user_score>
3 hữu ích 0 bình luận chia sẻ
0

Tôi thấy câu trả lời ban đầu vô cùng hữu ích nhưng tôi cũng muốn lấy một tập hợp các hàng nhất định dựa trên số hàng mà tôi đang chèn. Do đó, tôi gói toàn bộ câu trả lời ban đầu trong một truy vấn con để tôi có thể tham chiếu số hàng mà tôi đang chèn.

SELECT * FROM 
( 
    SELECT *, @curRow := @curRow + 1 AS "row_number"
    FROM db.tableName, (SELECT @curRow := 0) r
) as temp
WHERE temp.row_number BETWEEN 1 and 10;

Việc có một truy vấn con trong một truy vấn con không hiệu quả lắm, vì vậy, bạn nên kiểm tra xem liệu bạn có nhận được kết quả tốt hơn hay không bằng cách để máy chủ SQL của bạn xử lý truy vấn này hoặc tìm nạp toàn bộ bảng và để ứng dụng / máy chủ web thao tác các hàng sau thực tế .

Theo cá nhân tôi, máy chủ SQL của tôi không quá bận, vì vậy việc để nó xử lý các truy vấn con lồng nhau là điều nên làm.

0 hữu ích 0 bình luận chia sẻ
0

Tôi biết OP đang yêu cầu một mysqlcâu trả lời nhưng vì tôi thấy các câu trả lời khác không phù hợp với tôi,

  • Hầu hết trong số họ thất bại với order by
  • Hoặc chúng chỉ đơn giản là rất kém hiệu quả và làm cho truy vấn của bạn rất chậm đối với một bảng béo

Vì vậy, để tiết kiệm thời gian cho những người khác như tôi, chỉ cần lập chỉ mục hàng sau khi truy xuất chúng từ cơ sở dữ liệu

ví dụ trong PHP:

$users = UserRepository::loadAllUsersAndSortByScore();

foreach($users as $index=>&$user){
    $user['rank'] = $index+1;
}

ví dụ trong PHP sử dụng bù đắp và giới hạn cho phân trang:

$limit = 20; //page size
$offset = 3; //page number

$users = UserRepository::loadAllUsersAndSortByScore();

foreach($users as $index=>&$user){
    $user['rank'] = $index+1+($limit*($offset-1));
}
0 hữu ích 0 bình luận chia sẻ
loading
Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ mysql indexing , hoặc hỏi câu hỏi của bạn.

Có thể bạn quan tâm

loading