mysql works fine after first time - mysql

I have a strange problem which is when I run the sql command first time it shows wrong result, but when I run the same code for second time the result is correct.
The wrong result is:
The expected result is:
the sql command is:
SELECT srNumber, end_on, start_on, teamEntityId
FROM (
SELECT srNumber, end_on, start_on, teamEntityId,
#lastrow := IF(#sr_Number = srNumber, #lastrow + 1,
IF(#sr_Number := srNumber, 1, 0)) AS lastrow
FROM assign
CROSS JOIN (SELECT #lastrow := 0, #sr_Number = '') AS vars
ORDER By srNumber, assignId DESC) AS t
WHERE t.lastrow = 1 AND t.teamEntityId = '00000168752ac161-02420aff00230001'

In more recent versions of MySQL, you need to order the data before using variables. So replace:
FROM assign
with:
FROM (SELECT a.* FROM assign a ORDER BY srNumber, assignId DESC) a

I would like to thank Alex and Salman A who solved the problem which is:
replace the below code
#sr_Number = ''
to
#sr_Number := ''

Related

Port MySQL script to MS SQL -> simultaneous data asignement and retrieval

I have been trying to make this work for hours but I can't really find a way to do it. I have a MySQL script that I need to migrate to MS SQL 2014, however, I can't seem to make it work. As far as I have understood, the big issue is that MySQL allows this kind of instructions:
SELECT #row_number = #row_number + 1, hora_int FROM table1;
where you assign a value at the same time you retrieve data, but MS SQL does not.
I have a relatively big script which has that issue:
SELECT GLOBAL.year, GLOBAL.month, '1111111' as metric_id, GLOBAL.margin as metric_value FROM (SELECT A.year,
A.month,
CASE
WHEN A.month = 1 THEN (#csum_fdo := A.imp)
ELSE (#csum_fdo := #csum_fdo + A.imp) END as margin
FROM (SELECT Act.year, Act.month, Act.imp - Pas.imp as imp
FROM (SELECT year(tie.date) as year, month(tie.date) as month, sum(importe) as imp
FROM accounting con,
dim_time tie,
dim_account cta
WHERE con.account_date = tie.date
AND con.account = cta.nivel_10
AND cta.level_id = '2'
AND con.subtype_id <> 'O'
GROUP BY year(tie.date),
month(tie.date)) Act,
(SELECT year(tie.date) as year, month(tie.date) as month, sum(importe) * -1 as imp
FROM accounting con,
dim_time tie,
dim_account cta
WHERE con.account_date = tie.date
AND con.account = cta.nivel_10
AND cta.level_id = '3'
AND con.subtype_id <> 'O'
GROUP BY year(tie.date),
month(tie.date)) Pas
WHERE Act.year = Pas.year
AND Act.month = Pas.month) A,
(SELECT #csum_fdo := 0) E) GLOBAL
Can anybody point me in the direction of what I have to do to recreate the code in MS SQL? Thank you all in advance
In SQL Server and (MyQL 8+), you use window functions. The equivalent of:
SELECT #row_number = #row_number + 1, hora_int
FROM table1
ORDER BY col;
is:
SELECT ROW_NUMBER() OVER (ORDER BY col), hora_int
FROM table1;
If you provide sample data and desired results, it is much easier to figure out what functions you really need.
My big problem lied in this line:
CASE
WHEN A.month = 1 THEN (#csum_fdo := A.imp)
ELSE (#csum_fdo := #csum_fdo + A.imp) END as margin
but as Gordon Linoff pointed me. this problem could be solved with window functions, the right translation od that function is:
SUM(A.imp) OVER(PARTITION BY A.Year ORDER BY A.month) as margin
it ended up being easier than I thought
Thanks a lot and I hope it can help others as well

sql rank row results

I"m trying to add a new col that shows the rank (or sequence) of row results by date.
I've written:
SELECT
#row_number:=(CASE
WHEN #member_id = lh.member_id and lc.ladder_advocacy is not null
THEN #row_number + 1
when #member_id = lh.member_id and lc.ladder_advocacy is null then "null"
ELSE 1 /* there is an error here - i need it to return a 1 if not null, then 2 for the 2nd instance, etc */
END) AS rank_advocacy,
#member_id:=lh.member_id AS member_id,
lh.ladder_change,
lc.name,
lc.ladder_advocacy,
lc.ladder_elected,
lc.ladder_policy,
lc.ladder_engagement,
lc.ladder_newventure,
lc.ladder_collective,
lc.is_trigger
FROM
leenk_ladder_history AS lh
LEFT JOIN
leeds_so.leenk_ladder_config AS lc ON lh.ladder_config_id = lc.id
WHERE
ladder_change = 1 AND trigger_active = 1
ORDER BY member_id, trigger_event_date DESC;
There is an error at row 4, and I'm not sure how to fix it. For the first result, I want to return 1. for the second results, I want to return #row_number + 1. Third result, #row_number+2 (etc).
How do I achieve this?
I don't understand how the condition lc.ladder_advocacy is not null is being used. However, the basic structure is:
SELECT (#row_number = IF(#member_id = lh.member_id, #row_number + 1
IF(#member_id := lh.member_id, 1, 1)
)
) as rank_advocacy,
lh.ladder_change,
. . .
Some really important points:
You need to assign #member_id and #row_number in the same expression. MySQL (as with all other databases) does not guarantee the order of evaluation of expressions.
In more recent versions of MySQL, I think the ORDER BY needs to go in a subquery, with the variable expressions in the outer query.

mysql variable with #variables for calculated values

I have a mysql query where I need to calculate values like ROUND(SUM(temp.total_pq),2) multiple times, so I defined variables to avoid repeating them.
But the line 5 in the query returns wrong value in the results. The value for #diff_client_partner_qtty := ROUND((#partner_qtty_all_runs - #client_qtty_all_runs), 2) AS diff_client_partner_qtty is always NULL the first time I run and thereafter always 84.
I asked the in-house DBA and he says I should not use variables in my query like this because the order in which mysql will set values for the variable is not predictable and hence I may get NULL value.
But why? Also can someone please propose then another way whereby I can avoid rewriting ROUND(SUM(temp.total_pq),2) multiple times other than a subquery. I would prefer to avoid a subquery because I think even in its current form query is not that readable.
SELECT temp.dtaccounted AS accounting_period,
#partner_qtty_all_runs := ROUND(SUM(temp.total_pq),2) AS partner_qtty_all_runs,
ROUND(temp.mmq,2) AS mopay_qtty,
#client_qtty_all_runs := ROUND(SUM(temp.total_cq),2) AS client_qtty_all_runs,
#diff_client_partner_qtty := ROUND((#partner_qtty_all_runs - #client_qtty_all_runs), 2) AS diff_client_partner_qtty,
#partner_gtv := ROUND(temp.total_pq_gtv, 2) AS partner_gtv,
#client_gtv := ROUND(temp.total_cq_gtv,2) AS client_gtv,
#diff_client_partner_gtv := ROUND((#partner_gtv - #client_gtv), 2) AS diff_client_partner_gtv,
temp.stariffcurrency AS tariffcurrency,
ROUND(#diff_client_partner_gtv * ffactor, 2) AS diff_client_partner_gtv_eur,
temp.scountry AS country,
temp.spartnererpid AS partner_erp_id,
c.name AS partner_name,
temp.nproducttype AS product,
temp.capping
FROM
(SELECT SUM(npartnerquantity) AS total_pq,
SUM(nmindmaticsquantity) AS mmq,
SUM(nclientquantity) AS total_cq,
SUM(dgrosstariff * npartnerquantity) AS total_pq_gtv,
SUM(dgrosstariff * nclientquantity) AS total_cq_gtv,
nrun,
vb.scountry,
vb.spartnererpid,
dtaccounted,
stariffcurrency,
vb.nproducttype,
cq.bisenabled AS capping
FROM report_table vb,
client_table cq
WHERE vb.accperiod > '2013-12-01'
AND vb.partnerid = cq.partnerid
AND vb.scountry = cq.scountry
AND vb.nproducttype = cq.nproducttype
AND (cq.dtvalidto IS NULL
OR cq.dtvalidto > vb.accperiod)
GROUP BY scountry,
nproducttype,
partnerid,
nrun,
accperiod
) temp,
customer c,
currency_conversion cc
WHERE temp.partnerid = c.erp_id
AND temp.total_pq <> temp.total_cq
AND cc.scurrencyfrom = temp.stariffcurrency
AND cc.scurrencyto = 'EUR'
AND cc.dtrefdate = temp.accperiod
GROUP BY temp.scountry,
temp.partnerid,
c.name,
temp.nproducttype,
temp.accperiod
ORDER BY temp.accperiod,
temp.scountry,
temp.partnerid,
temp.nproducttype,
temp.capping \G;

Coldfusion CFScript Query with MySQL Assignment Operator

I want to select currentrow as part of my query - I know I can loop over queries and get the currentrow variable, but I'm doing a QoQ before I use the rows and I want to keep the original rows, e.g.
//Original query
1, Audi
2, BMW
3, Skoda
//QoQ
1, Audi
3, Skoda
This is the code I've got:
q = new Query( datasource = application.db.comcar );
q.setSQL('
SELECT make, #rownum := #rownum +1 AS `rownumber`
FROM cars, ( SELECT #rownum :=0 )
LIMIT 10
');
r = q.execute().getResult();
But it's throwing the following error:
Parameter '=' not found in the list of parameters specified
SQL: SELECT make, #rownum := #rownum + 1 AS `rownumber` FROM cars, ( SELECT #rownum :=0 ) LIMIT 10
This will work in cfquery but I'd like to use it in CFScript. Is there an alternative to using := or some way of escaping this in the query.
It looks like this is a bug in Coldfusion. I could change my code to use cfquery but I'd rather not mix script and tags in my page.
So my workaround was is as follows:
/*
* based on the existing query 'tmpFields'
*/
// build array of row numbers
arrRowNumbers = [];
cntRowNumbers = tmpFields.recordCount;
for( r = 1; r <= cntRowNumbers; r++ ) {
arrayAppend( arrRowNumbers, r );
}
// add a new column with the new row number array
queryAddColumn( tmpFields, "fieldNumber", "integer", arrRowNumbers );

mysql create view with mysql query that contains variable

I have the below syntax that I want to use to create a MySQL view:
create view `ViewName` as (select
v_starting.callingname,
v_starting.geofence,
v_starting.`updatetime`,
#lastGroup := #lastGroup + if( #lastAddress = v_starting.geofence
AND #lastVehicle = v_starting.callingname, 0, 1 ) as GroupSeq,
#lastVehicle := v_starting.callingname as justVarVehicleChange,
#lastAddress := v_starting.geofence as justVarAddressChange
from
v_starting,
( select #lastVehicle := '',
#lastAddress := '',
#lastGroup := 0 ) SQLVars
order by
v_starting.`updatetime` )
This fails with error:
#1351 - View's SELECT contains a variable or parameter
How can I get around this? Thanks a million.
As documented under CREATE VIEW Syntax:
A view definition is subject to the following restrictions:
[ deletia ]
The SELECT statement cannot refer to system or user variables.
Think you would need to do this using a subselect to count the records.
Something like this:-
SELECT v_starting.callingname,
v_starting.geofence,
v_starting.`updatetime`,
Sub1.PrevRecCount ASGroupSeq
FROM v_starting
INNER JOIN (SELECT a.updatetime, COUNT(DISTINCT b.callingname, b.geofence ) AS PrevRecCount
FROM v_starting a
LEFT OUTER JOIN v_starting b
ON a.updatetime > b.updatetime
AND a.callingname != b.callingname
AND a.geofence != b.geofence
GROUP BY a.updatetime) Sub1
Not 100% sure about this as I am dubious about how you are ordering things to get your count presently.
for variable using, try to use a stored procedure or a custom function