I'm trying to convert this mysql query to run on SQL but having some issues with the syntax on join. Basically what I want to do is set the DWH_HISTO to 1 on duplicate rows based on the DWH_DATE. So the older duplicates should be marked.
This is what I've tried
UPDATE MAG_L_D3.dbo.INSCRIPT
INNER JOIN
(SELECT MAX(DWH_DATE) as lastId, CODINS
FROM INSCRIPT
WHERE DWH_HISTO=0
GROUP BY CODINS
HAVING COUNT(*) > 1) duplic on duplic.CODINS = MAG_L_D3.dbo.INSCRIPT.CODINS
SET DWH_HISTO = 1
WHERE MAG_L_D3.dbo.INSCRIPT.DWH_DATE < duplic.lastId
I believe this is the syntax you are looking for:
;WITH CTE as
(
SELECT *, row_number() over (partition by CODINS order by DWH_DATE desc)rn
)
UPDATE CTE
SET DWH_HISTO = 1
WHERE
rn > 1
and DWH_HISTO=0
Update using inner join:
UPDATE I
SET DWH_HISTO = 1 FROM MAG_L_D3.dbo.INSCRIPT I
INNER JOIN
(SELECT MAX(DWH_DATE) as lastId, CODINS
FROM INSCRIPT
WHERE DWH_HISTO=0
GROUP BY CODINS
HAVING COUNT(*) > 1) duplic on duplic.CODINS = I.CODINS
WHERE I.DWH_DATE < duplic.lastId
Related
I am having a issue related to Snowflake. When I run the below query, I do get 'Single-row subquery returns more than one row.'
Do you have any idea on how to fix this issue?
Below is the query
SELECT DISTINCT J.JOB_ID , J.ACCEPTED_DATE ,
(SELECT DOCUMENT_ID FROM (SELECT DD.DOCUMENT_ID ,row_number() over (partition by DD.DOCUMENT_ID order by DD.DOCUMENT_ID ) as row_number
FROM SFG.RCM_JOB_INDUSTRY DD
LEFT JOIN USERS_L.JOB_MASTER J ON DD.JOB_ID = J.JOB_ID) WHERE row_number=1) AS DOCUMENT_ID,
(SELECT U.USERNAME FROM SFL.RCS_USER U LEFT JOIN SMW.RCS_STATUS RS ON RS.USER_ID = U.USER_ID) AS REPAIRED_BY
FROM USERS_L.JOB_MASTER J
Thank you
There are 2 subqueries, and I suspect the second one causing the issue:
SELECT
DISTINCT J.JOB_ID,
J.ACCEPTED_DATE,
(
SELECT
DOCUMENT_ID
FROM
(
SELECT
DD.DOCUMENT_ID,
row_number() over (
partition by DD.DOCUMENT_ID
order by
DD.DOCUMENT_ID
) as row_number
FROM
SFG.RCM_JOB_INDUSTRY DD
LEFT JOIN USERS_L.JOB_MASTER J ON DD.JOB_ID = J.JOB_ID
)
WHERE
row_number = 1
) AS DOCUMENT_ID,
(
SELECT
TOP 1 U.USERNAME
FROM
SFL.RCS_USER U
LEFT JOIN SMW.RCS_STATUS RS ON RS.USER_ID = U.USER_ID
) AS REPAIRED_BY
FROM
USERS_L.JOB_MASTER J
https://docs.snowflake.com/en/sql-reference/constructs/top_n.html
I need to update CTE o/p one of the column value (top 1 record) based on the latest timestamp & then return.
Query
WITH cte AS (
select
dt_zone.zone_name,
dt_material_status.mtstatus_name,
dt_historicalzone.visit_time_in
FROM ((public.dt_historicalzone
INNER JOIN dt_material_status
ON dt_historicalzone.mtstatus_id = dt_material_status.mtstatus_id)
INNER JOIN dt_zone ON dt_historicalzone.zone_id = dt_zone.zone_id)
WHERE material_id = 'ELS46885'
ORDER BY dt_historicalzone.zone_id DESC)
UPDATE cte SET cte.mtstatus_name = true WHERE SELECT * FROM cte LIMIT 1;
SELECT * FROM cte
You may try using an update join, with Postgres' syntax, including a CTE for the limit portion of the query:
WITH cte AS (
SELECT dh.mtstatus_id
FROM dt_historicalzone dh
INNER JOIN dt_zone dz
ON dh.zone_id = dz.zone_id
ORDER BY zone_id DESC
LIMIT 1
)
UPDATE dt_material_status d
SET mtstatus_name = true
FROM cte t
WHERE d.mtstatus_id = t.mtstatus_id AND
d.material_id = 'ELS46885';
when you update a CTE, the background table is getting updated. You can have only one statement below CTE. Post that CTE loses its scope. You can only go for UPDATE statement, post CTE. I have modified the CTE and updated the top 1 row.
The above statement is applicable for SQL Server. In Postgres, the CTE cannot be target of UPDATE statements. See the below error in Postgres.
Query Error: error: relation "cte" cannot be the target of a modifying
statement
WITH cte AS (
select top 1
dt_zone.zone_name,
dt_material_status.mtstatus_name,
dt_historicalzone.visit_time_in
FROM public.dt_historicalzone
INNER JOIN dt_material_status
ON dt_historicalzone.mtstatus_id = dt_material_status.mtstatus_id
INNER JOIN dt_zone ON dt_historicalzone.zone_id = dt_zone.zone_id
WHERE material_id = 'ELS46885'
ORDER BY dt_historicalzone.zone_id DESC)
UPDATE cte
SET mtstatus_name = true
I have tried with sample data for a CTE update. Below works fine in SQL Server.
create table #test(a int)
create table #test2(a int, b int)
insert into #test values (1)
insert into #test2 values (1,1)
;WITH CTE as
(
select top 1 t.a, t2.b
FROM #test as t
join #test2 as t2
on t.a = t2.a
order by t.a desc
)
update cte set b = 0
select * from #test2
With this query what I need SQL to do is update a column value based on another column so that it grabs the most recent MAX ID.
select
max(T1id), t1.v_code
from
[Table1] T1
join
[Table2] t2 on t1.T1Code = t2.T2Code
where
t2.active = 0
and t1.t1activesw = 0
and t1.mapping not like '%selected%'
group by
t1.v_code
I'd like to join the select to the table on the version code id = max(t1.v_code) and then use the code as a sub select just not sure how to finish it.
With this, you get all data from the row for with the highest T1.id for each T1.v_code:
;WITH CTE as
(
SELECT
T1.*,
row_number() over (partition by T1.v_code order by T1.id desc) rn
FROM
[Table1] T1
JOIN
[Table2] t2 on t1.T1Code = t2.T2Code
WHERE
t2.active = 0
and t1.t1activesw = 0
and t1.mapping not like '%selected%'
)
SELECT *
FROM CTE
WHERE rn = 1
Edit: In order to update, replace(as requested in commment)
SELECT *
FROM CTE
WHERE rn = 1
with
UPDATE CTE
SET columnname = 'newvalue'
WHERE rn = 1
this
Here is my table
And my output should be
I want to update the closed_date,time for new_class_desc ='FLM' with next Update_date,Update_time but if new_class_desc is 'FollowupComments' then ignore it and update the next date as Closed_date
I was trying query somewhat like this..
;WITH cte as(
SELECT *
,row_number() OVER(ORDER BY Update_date,Update_time) rn
FROM Table
WHERE Problem_sid = 1435819
)
UPDATE c1 SET Closed_date = c2.Update_date, Closed_time = c2.Update_time
FROM cte c1
JOIN cte c2 ON c1.rn = c2.rn - 1
AND c1.New_class_desc = 'FLM'
AND c2.New_class_desc <> 'FLM'
AND c2.New_class_desc not in ('FollowUpComments')
But in this I am not getting new_class_desc =Bank update_date as Closed_date for Flm.
Please guide here.
WITH cte
AS
(
SELECT *, ROW_NUMBER() OVER(ORDER BY t.Update_date, t.Update_time) AS rno
FROM my_Table t
WHERE t.New_class_desc <> 'FollowUpComments'
)
UPDATE t
SET t.Closed_Date = t1.Closed_Date,
t.Closed_Time = t1.Closed_Time
FROM cte t
JOIN cte t1 ON t.rno = t1.rno + 1
WHERE t.New_class_desc = 'FLM'
I have this query:
SELECT * FROM ( SELECT ROW_NUMBER() OVER (ORDER BY CASE WHEN ISNUMERIC(dtLu.sLu) = 1 THEN CONVERT(INT, dtLu.sLu) ELSE 9999999 END asc, dtLu.sLu) as row,
dtLu.*, dtLuDerived.cCll, dtMtrDerived.cMtrCll, dtMtrDerived.cMtrCllIn, dtMtrDerived.cMtrCllOut FROM dtLu
LEFT OUTER JOIN (
SELECT pLu, COUNT(pLu) AS cCll
FROM dtCll
GROUP BY pLu)
AS dtLuDerived ON dtLu.pLu = dtLuDerived.pLu
LEFT OUTER JOIN (
SELECT dtCll.pLu, SUM(cMtrCll) AS cMtrCll, SUM(cMtrCllIn) AS cMtrCllIn, SUM(cMtrCllOut) AS cMtrCllOut
FROM dtMtrCll
INNER JOIN dtCll on dtCll.pCll = dtMtrCll.pCll
WHERE dtCll.pWhr IN (SELECT DISTINCT pWhr FROM dtUserWhr WHERE pUser = 5)
GROUP BY dtCll.pLu)
AS dtMtrDerived ON dtLu.pLu = dtMtrDerived.pLu
INNER JOIN dtLct on dtLct.pLct = dtLu.pLct
WHERE dtLu.pLu > 0 AND dtLct.pLctAsl IN (select pAsl from dtAsl where pAslUnt = 1)
-- this is the ORDER I need
ORDER BY dtLu.pLct DESC
) a
WHERE a.row > 0 and a.row <= 17
but if I use the order ORDER BY dtLu.pLct DESC it gives me error...
The ORDER BY clause is invalid in views, inline functions, derived
tables, subqueries, and common table expressions, unless TOP, OFFSET
or FOR XML is also specified.
I searched, found various samples, but my subquery is different, 'cause is needed to retrieve only 17 rows per page (next page will have the last line like this: WHERE a.row > 17 and a.row <=35)
how can I select the top 17 rows but with an order inside?
thanks
You are trying to put the order in your inner query which doesn't work. Move the order by to the main query. Also, you should list your columns instead of using *. You could probably improved this query a bit with fewer subselects but that is outside the scope of your question.
SELECT * FROM ( SELECT ROW_NUMBER() OVER (ORDER BY CASE WHEN ISNUMERIC(dtLu.sLu) = 1 THEN CONVERT(INT, dtLu.sLu) ELSE 9999999 END asc, dtLu.sLu) as row,
dtLu.* --you should list the columns out here
, dtLuDerived.cCll, dtMtrDerived.cMtrCll, dtMtrDerived.cMtrCllIn, dtMtrDerived.cMtrCllOut FROM dtLu
LEFT OUTER JOIN (
SELECT pLu, COUNT(pLu) AS cCll
FROM dtCll
GROUP BY pLu)
AS dtLuDerived ON dtLu.pLu = dtLuDerived.pLu
LEFT OUTER JOIN (
SELECT dtCll.pLu, SUM(cMtrCll) AS cMtrCll, SUM(cMtrCllIn) AS cMtrCllIn, SUM(cMtrCllOut) AS cMtrCllOut
FROM dtMtrCll
INNER JOIN dtCll on dtCll.pCll = dtMtrCll.pCll
WHERE dtCll.pWhr IN (SELECT DISTINCT pWhr FROM dtUserWhr WHERE pUser = 5)
GROUP BY dtCll.pLu)
AS dtMtrDerived ON dtLu.pLu = dtMtrDerived.pLu
INNER JOIN dtLct on dtLct.pLct = dtLu.pLct
WHERE dtLu.pLu > 0 AND dtLct.pLctAsl IN (select pAsl from dtAsl where pAslUnt = 1)
-- this is the ORDER I need
--ORDER BY dtLu.pLct DESC
) a
WHERE a.row > 0 and a.row <= 17
order by a.pLct
Use TOP 100 Percent in Subquery
SELECT *
FROM (SELECT top 100 percent Row_number()
OVER (
ORDER BY CASE WHEN Isnumeric(dtLu.sLu) = 1 THEN CONVERT(INT, dtLu.sLu) ELSE 9999999 END ASC, dtLu.sLu) AS row,
dtLu.*,
dtLuDerived.cCll,
dtMtrDerived.cMtrCll,
dtMtrDerived.cMtrCllIn,
dtMtrDerived.cMtrCllOut
FROM dtLu
LEFT OUTER JOIN (SELECT pLu,
Count(pLu) AS cCll
FROM dtCll
GROUP BY pLu) AS dtLuDerived
ON dtLu.pLu = dtLuDerived.pLu
LEFT OUTER JOIN (SELECT dtCll.pLu,
Sum(cMtrCll) AS cMtrCll,
Sum(cMtrCllIn) AS cMtrCllIn,
Sum(cMtrCllOut) AS cMtrCllOut
FROM dtMtrCll
INNER JOIN dtCll
ON dtCll.pCll = dtMtrCll.pCll
WHERE dtCll.pWhr IN (SELECT DISTINCT pWhr
FROM dtUserWhr
WHERE pUser = 5)
GROUP BY dtCll.pLu) AS dtMtrDerived
ON dtLu.pLu = dtMtrDerived.pLu
INNER JOIN dtLct
ON dtLct.pLct = dtLu.pLct
WHERE dtLu.pLu > 0
AND dtLct.pLctAsl IN (SELECT pAsl
FROM dtAsl
WHERE pAslUnt = 1)
-- this is the ORDER I need
ORDER BY dtLu.pLct DESC) a
WHERE a.row > 0
AND a.row <= 17