Why am I getting different results when running the same query, which include temporary variables, from node js as from MySQL?

Viewed 189

Here are the mysql table and data statements;

CREATE TABLE temp_sales (
    order_number INT,
    region varchar(20),
    currency varchar(3),
    sales_value decimal(13,2)
);

INSERT INTO temp_sales VALUES 
  (1, 'ASIA', 'JPY', 100.00),
  (2, 'ASIA', 'JPY', 200.00),
  (3, 'ASIA', 'JPY', 300.00),
  (4, 'AMERICAS', 'USD', 100.00),
  (5, 'AMERICAS', 'USD', 200.00),
  (6, 'AMERICAS', 'USD', 300.00);
 
CREATE TABLE temp_exchange_rate (
    currency varchar(3),
    exchange_rate decimal(5,2)
);

INSERT INTO temp_exchange_rate VALUES 
  ('JPY', 1.40),
  ('USD', 1.50);

To run this SQL;

SELECT   ms.order_number
        ,ms.region
        ,ms.sales_value * er.exchange_rate AS base_value
        ,ms.order_rank
FROM temp_exchange_rate er
inner join
(   SELECT   s.order_number
            ,s.region
            ,s.currency
            ,s.sales_value
            ,@order_rank := if(@sale_currency = s.currency, @order_rank + 1, 1) AS order_rank
            ,@sale_currency := s.currency
    from temp_sales AS s
    order by s.region 
            ,s.sales_value desc
) as ms on ms.currency = er.currency 
WHERE 1 = 1
and ms.order_rank = 1;

The results from MySQL v5.7 are as follows;

ms.order_number ms.region base_value ms.order_rank
3 ASIA 420.0000 1.0
6 AMERICAS 450.0000 1.0

If I put the same statement into node js and print out each record I get the following results ;

main #3 6
main #4 1 // ASIA // 140.0000 // 1
main #4 3 // ASIA // 420.0000 // 1
main #4 2 // ASIA // 280.0000 // 1
main #4 6 // AMERICAS // 450.0000 // 1
main #4 5 // AMERICAS // 300.0000 // 1
main #4 4 // AMERICAS // 150.0000 // 1
main #5

The issue appears to be the temporary variables @order_rank & @sale_currency which are NOT set correctly in nodejs

Here's the code ;

async function getSymbols4EOD(pool) {
    let uiStmt = `  SELECT   ms.order_number
                            ,ms.region
                            ,ms.sales_value * er.exchange_rate AS base_value
                            ,ms.order_rank
                    FROM temp_exchange_rate er
                    inner join
                    (   SELECT   s.order_number
                                ,s.region
                                ,s.currency
                                ,s.sales_value
                                ,@order_rank := if(@sale_currency = s.currency, @order_rank + 1, 1) AS order_rank
                                ,@sale_currency := s.currency
                        from temp_sales AS s
                        order by s.region 
                                ,s.sales_value desc
                    ) as ms on ms.currency = er.currency 
                    WHERE 1 = 1
                    and ms.order_rank = 1  `;

    console.log('getSymbols4EOD START');
    
    //  START
    const connection = await pool.getConnection();
    console.log('getSymbols4EOD POST CONNECTION');
    try {
        console.log('getSymbols4EOD PRE-QUERY', uiStmt);
        const results = await connection.query(uiStmt);

        connection.release();
        return results[0];
    }   catch (err) {
        console.log('getSymbols4EOD ERR', err);
        connection.release();
        throw err; // not connected!
    }
    //  END
}

async function main() {
    const mysql = require('mysql2/promise');
    
    const config = {
        host: 'localhost',
        user: 'blah',
        password: 'blahvlah',
        database: 'db-blah',
        waitForConnections: true,
        connectionLimit: 10,
        queueLimit: 0
    };
    const pool = mysql.createPool(config);
    console.log('main #1');

    try {
        console.log('main #2');
        let indexRows = await getSymbols4EOD(pool);
        console.log('main #3',indexRows.length);

        for (const row of indexRows) {
            console.log('main #4', row.order_number, '//', row.region, '//', row.base_value, '//', row.order_rank) ;
        }
    }   catch (err) {
        console.log('main #4a',err);
    }
    console.log('main #5');

    pool.end();
}

main();

So first question;

  1. Am I doing anything wrong ?
  2. Is there a different SQL statement which will give me the desired results ?
1 Answers

Try adding this into your subquery:

 SELECT   s.order_number
            ,s.region
            ,s.currency
            ,s.sales_value
            ,@order_rank := if(@sale_currency = s.currency, @order_rank + 1, 1) AS order_rank
            ,@sale_currency := s.currency
    from temp_sales AS s
    /*add a CROSS JOIN with a subquery that sets the variables to 0 here*/
    CROSS JOIN (SELECT @sale_currency := 0, @order_rank := 0) as n 
    order by s.region 
            ,s.sales_value desc

That should generate @order_rank accordingly.

Related