Search code examples
mysqlsqljoininner-joinouter-join

Replace mysql variables with Join


I am using MySQL 5-enterprise-commercial version. I have written the below 2 queries which I want to convert into a single query using join.

SET @row_number :=0;
SELECT
       @row_number:= case
            when @RId =  r_id then @row_number + 1
                else 1
            end as rnum,
        @RId:=r_id as r_id,
        msg,
        supplier,
        rrtry from (
            SELECT
                a.r_id as r_id,
                mta.message as msg,
                tpr.supplier as supplier,
                trw.retry as rrtry,
                a.createdAt as createdAt,
            FROM sa.nra a,
                sa.nmta mta,
                sa.treq tpr,
                sa.twflw trw
            WHERE tpr.n_r_id = a.r_id
                AND trw.astp = mta.stp
                AND mta.rstatus in ('FAIL')
                AND tpr.p_w_id = trw.id
                AND a.a_mid = mta.id
                AND a.createdAt  BETWEEN now() - interval 30 DAY AND now() 
            ORDER BY  a.r_id
) as  sa
HAVING rnum = 1
ORDER BY createdAt DESC;

Basically, there are multiple entries for r_id, and I want to get the latest entry for a particular r_id and that is why I am using ORDER BY a_createdAt DESC


Solution

  • Join the query with a subquery that uses the := operator to set the variable.

    SELECT
        @row_number:= case
            when @RId =  r_id then @row_number + 1
                else 1
            end as rnum,
        @RId:=r_id as r_id,
        msg,
        supplier,
        rrtry 
    from (
        SELECT
            a.r_id as r_id,
            mta.message as msg,
            tpr.supplier as supplier,
            trw.retry as rrtry,
            a.createdAt as createdAt
        FROM sa.nra a
        JOIN sa.nmta mta ON a.a_mid = mta.id
        JOIN sa.treq tpr ON tpr.n_r_id = a.r_id
        JOIN sa.twflw trw ON trw.astp = mta.stp AND tpr.p_w_id = trw.id
        WHERE mta.rstatus in ('FAIL')
        ORDER BY  a.r_id
    ) as  sa
    CROSS JOIN (SELECT @row_number := 0) AS vars
    HAVING rnum = 1
    ORDER BY a_createdAt DESC;
    

    I've replaced the cross-product in the subquery with ANSI JOIN.

    If you're using MySQL 8.0, you can use the RANK() or ROW_NUMBER() window functions instead of a user variable.