Search code examples
mysqlsqlauto-incrementrow-numberdense-rank

How to make a sequence number ranking in mysql


I have data like this:

id | md_name      | total_visit
===+==============+============
1  | Nunu Nugraha | 33
2  | Erwin        | 32
3  | Tri Sulistyo | 35
4  | Risdianto    | 24
5  | Erma         | 22
6  | Dwi Sabana   | 19
7  | Ernayanti    | 26
8  | Ali          | 10
9  | Partini      | 13

I made the above results with a join code like this:

SELECT datamd.id as id,
    datamd.nama_md as md_name,
    COUNT(R.id) as total_visit
    FROM datamd
    LEFT JOIN
    (
        SELECT id, idmd
        FROM rincian_kunjungan WHERE status='1' AND MONTH(tanggal_kunjungan)='$bulan' AND YEAR(tanggal_kunjungan)='$tahun'
    ) AS R
        ON datamd.id = R.idmd WHERE status=1 AND level=8 GROUP BY datamd.id ORDER BY datamd.id

And I want to be like this:

rank | id | md_name      | total_visit
=====+====+==============+============
  1  | 3  | Tri Sulistyo | 35
  2  | 1  | Nunu Nurgaha | 33
  3  | 2  | Erwin        | 32
  4  | 7  | Ernayanti    | 26
  5  | 4  | Risdianto    | 24
  6  | 5  | Erma         | 22
  7  | 6  | Dwi Sabana   | 19
  8  | 9  | Partini      | 13
  9  | 8  | Ali          | 10

Can friends here help me, I have tried using the code below but in the ranking column it is not appropriate

SET @number = 0;
SELECT @number:=@number+1 as rank, datamd.id as id,
    datamd.nama_md as md_name,
    COUNT(R.id) as total_visit
    FROM datamd
    LEFT JOIN
    (
        SELECT id, idmd
        FROM rincian_kunjungan WHERE status='1' AND MONTH(tanggal_kunjungan)='$bulan' AND YEAR(tanggal_kunjungan)='$tahun'
    ) AS R
        ON datamd.id = R.idmd WHERE status=1 AND level=8 GROUP BY datamd.id ORDER BY rank ASC

Solution

  • You can fight user variables all day or emulate dense rank function in MySQL like so:

    SELECT main.id, main.md_name, main.total_visit, COUNT(DISTINCT prev.total_visit) + 1 AS rank
    FROM datamd AS main
    LEFT JOIN datamd AS prev ON prev.total_visit > main.total_visit
    GROUP BY main.id, main.md_name, main.total_visit
    ORDER BY rank
    

    Substitute the "tables" in the above query with the sub queries from your original query:

    SELECT datamd.id, datamd.nama_md, main.total_visit, COUNT(DISTINCT prev.total_visit) + 1 AS rank
    FROM datamd
    LEFT JOIN (
        SELECT idmd, COUNT(*) AS total_visit
        FROM rincian_kunjungan
        WHERE status = '1' AND MONTH(tanggal_kunjungan) = $bulan AND YEAR(tanggal_kunjungan) = $tahun
        GROUP BY idmd
    ) AS main ON datamd.id = main.idmd
    LEFT JOIN (
        SELECT COUNT(*) AS total_visit
        FROM rincian_kunjungan
        WHERE status = '1' AND MONTH(tanggal_kunjungan) = $bulan AND YEAR(tanggal_kunjungan) = $tahun
        GROUP BY idmd
    ) AS prev ON prev.total_visit > main.total_visit
    GROUP BY datamd.id, datamd.nama_md, main.total_visit
    ORDER BY rank