I have a complicated SQL query running on a MSSQL server. I need to change it to make it work also on a MySQL database, however I do not know how to do this. The query is the following and is used to build a complicated Sankey graph in a BI tool
SELECT Id, Delivery_Date, Queue, Step1, Step2, Step3, Step4, Step5, Step6, Step7,
CONVERT(DECIMAL(16,16),RAND((CHECKSUM(NEWID())))*(1 - 0.999999999)+0.999999999) as Counter
FROM
(SELECT t.ID as Id, t.DELIVERY_DATE as Delivery_Date, t.QUEUE as Queue, CONCAT(t.EVENT_NAME,' ', t.EVENT_STATUS, ' ',t .ENDING) as edsda,
'Step' + cast(row_number() over (partition by ID order by ID)
as varchar(10)) ColumnSeq
FROM (SELECT DISTINCT e.[ID] AS ID,
e.[DIALOG_DELIVERY_DATE] AS DELIVERY_DATE,
e.[QUEUE_ID] as QUEUE,
s2.[STEP_NUMBER] AS STEP_NUMBER,
s2.[CURRENT_EVENT] AS EVENT_NAME,
s2.[EVENT_STATUS] as EVENT_STATUS,
e.[DELIVERY_END] AS DELIVERY_END,
CASE WHEN s2.[STEP_NUMBER] = max(s2.[STEP_NUMBER]) over (partition by s2.[ID])
and s2.[EVENT_NUMBER] = min(s2.[EVENT_NUMBER]) over (partition by s2.[ID], s2.[STEP_NUMBER]) THEN e.[DELIVERY_END] ELSE NULL END as ENDING
FROM [dbo].[DELIVERY_STEP_EVENTS] s1,
[dbo].[DELIVERY_STEP_EVENTS] s2,
[dbo].[DELIVERY_EVENTS] e
WHERE s1.[ID] = s2.[ID]
AND e.[ID] = s2.[ID]
AND s1.[EVENT_NAME] = s2.[EVENT_NAME]
AND s1.[STEP_NUMBER] <= s2.[STEP_NUMBER] AS t) AS temp
pivot
(max(edsda)
for ColumnSeq in (Step1,Step2,Step3,Step4, Step5, Step6, Step7)
)
AS Piv
My biggest issue so far has been the RAND((CHECKSUM(NEWID()))) which I do not know how to change to MySQL.
Any help would be greatly appreciated.
My biggest issue so far has been the RAND((CHECKSUM(NEWID()))) which I
do not know how to change to MySQL.
RAND((CHECKSUM(NEWID()))) should behave identical to RAND() function in MySQL. So you could simply replace this:
CONVERT(DECIMAL(16,16),RAND((CHECKSUM(NEWID())))*(1 - 0.999999999)+0.999999999)
With this:
CAST(RAND() * (1 - 0.999999999) + 0.999999999 AS DECIMAL(16, 16))
SQL Server
MySQL
Related
I have a Device that send event on a SQL data base. The event a log like this:
index|eventNumber|TriggerTime|RecoverTime
The issue I have is if they have a power off/on on the device it create sont unrecover event like this
index|eventNumber|TriggerTime|RecoverTime
1|2|2020-04-03 8:00|2020-04-03 8:10
2|3|2020-04-03 8:00|2020-04-03 8:30
3|3|2020-04-03 8:20|NULL
4|2|2020-04-03 8:21|2020-04-03 8:23
5|3|2020-04-03 8:40|NULL
What I want to do is to copy the triggerTime of the next event with the same eventNumber in the recoverTime. Like this
index|eventNumber|TriggerTime|RecoverTime
1|2|2020-04-03 8:00|2020-04-03 8:10
2|3|2020-04-03 8:00|2020-04-03 8:30
3|3|2020-04-03 8:20|2020-04-03 8:40
4|2|2020-04-03 8:21|2020-04-03 8:23
5|3|2020-04-03 8:40|NULL
What is the best way to do this?
You can use lead():
select el.*,
coalesce(recovertime,
lead(triggertime) over (partition by eventnumber order by triggertime)
) as new_recovertime
from eventlog;
If you need this in an update, you can use join
update eventlog el join
(select el.*,
lead(triggertime) over (partition by eventnumber order by triggertime) as new_recovertime
from eventlog
) el2
on el2.eventnumber = el.eventnumber and
el2.eventtime = el.eventtime
set recovertime = new_recovertime
where recovertime is null and new_recovertime is not null;
the mysql server is 5.7, so it doesn't have the lead fonction. I find a way to do a select to that add a colone with the value to put in the null place, but I don't know how to put it in an update.
(SELECT
event_index, event_log_index, `trigger_time#timestamp`, `recover_time#timestamp`
, (SELECT
`trigger_time#timestamp`
FROM
plc.`test` alfabetInner
WHERE
alfabetInner.`trigger_time#timestamp` > plc.`test`.`trigger_time#timestamp` AND alfabetInner.`event_log_index` = plc.`test`.`event_log_index`
ORDER BY
`trigger_time#timestamp` ASC
LIMIT 0, 1
) AS 'Nexttrigger_time#timestamp'
FROM
plc.`test`
ORDER BY
`trigger_time#timestamp` ASC)
The problem is that when I'm inserting data on tbl_tramite, the query doesn't recognize random_number value. It says unknown column 'random_number' in "IN/ALL/ANY" subquery. All of this using MySQL.
This is for a C# Winforms application with MariaDB 10.3, this query inserts on 2 tables but random_number is inserted on tbl_tramite.
START TRANSACTION;
INSERT IGNORE tbl_solicitante (cedula, solicitante, telefono, distrito, comunidad, estado)
VALUES(ced, sol, tel, dist, com, 'A');
SELECT LPAD(FLOOR(RAND() * 999999.99), 4) AS random_number
FROM tbl_tramite
WHERE random_number NOT IN (SELECT id_caso FROM tbl_tramite) LIMIT 1;
SET #caso := CONCAT(ced, random_number);
INSERT INTO tbl_tramite (id_caso, solicitante_cedula, usuario_id_usuario, operacion_id_operacion, inspector, detalle, estado,
fecha_ingreso, fecha_regreso_inspeccion, fecha_aprobacion, fecha_entrega)
VALUES(#caso , ced, func, tra, insp, det, est, fech1, fech2, fech3, fech4);
COMMIT;
Tested this fragment only:
SELECT LPAD(FLOOR(RAND() * 999999.99), 4) AS id_tramite
FROM tbl_tramite
WHERE id_tramite NOT IN (SELECT id_tramite FROM tbl_tramite);
Doesn`t return any record.
I expect random_number to be recognized and then to use it to concatenate it with a unique id so the other insert statement uses it. I'm receiving a message from try-catch on c# that says that random_number column field list doesn't exist.
I solved this using this statement:
SET #valor = (SELECT NUM FROM(SELECT LPAD(FLOOR(RAND() * 999999.99), 7) AS NUM) AS SUBQ WHERE NUM NOT IN (SELECT id_caso FROM tbl_tramite) LIMIT 1);
I'm using HeidiSQL so I don't know if it was this or something else but in order to make it works I had to surround the query with parentheses.
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
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;
I have the an existing table that for some reason the designer decided to manually control the Primary Key value by storing the last used value in a seperate table (changing the table to use Identity is not an option right now).
I now need to do a mass update to this table as follows:
DECLARE #NeedFieldID int
SET #NeedFieldID = 62034
INSERT INTO T_L_NeedField (NeedID, NeedFieldID, FieldName, Sequence, DisplayAs, FieldPrompt, DataType, ValidOptions, IsRequiredForSale)
(
SELECT
DISTINCT n.NeedID,
#NeedFieldID + 1,
'DetailedOutcome',
999,
'Detailed Outcome',
'Select appropriate reason for a No Sale outcome',
'T',
'Pricing, Appointment Date / Time Not Available, Will Call Back, Declined',
0
FROM T_L_Need n
INNER JOIN T_L_NeedField nf
ON n.NeedID = nf.NeedID
WHERE (n.Need LIKE 'Schedule%' AND n.Disabled = 0)
)
Obviously '#NeedFieldID + 1' doesn't work (just using it to show what I want to do). How can I increment #NeedFieldID as SQL inserts the values for each of the distinct NeedId's? I am using SQL Server 2008.
You want row_number():
DECLARE #NeedFieldID int
SET #NeedFieldID = 62034
INSERT INTO T_L_NeedField (NeedID, NeedFieldID, FieldName, Sequence, DisplayAs, FieldPrompt, DataType, ValidOptions, IsRequiredForSale)
(
SELECT
DISTINCT n.NeedID,
#NeedFieldID + row_number() over (order by n.NeedID),
'DetailedOutcome',
999,
'Detailed Outcome',
'Select appropriate reason for a No Sale outcome',
'T',
'Pricing, Appointment Date / Time Not Available, Will Call Back, Declined',
0
FROM T_L_Need n
INNER JOIN T_L_NeedField nf
ON n.NeedID = nf.NeedID
WHERE (n.Need LIKE 'Schedule%' AND n.Disabled = 0)
)
However, your best bet is to make NeedFieldID an identity column and just let SQL Server do the work for you.