SQL How to UPDATE Column via subquery with condition - sql-server

Is it possible to update my a column in my table via subquery? the unique value is [ID] and [Date] How can I do this. So far I tried it like this but failed
UPDATE [dbo].[SCPL_EOD]
SET [CSP] = (SELECT
D.CSP FROM
(
SELECT PDT.CallID,SCP.*
,ROW_NUMBER() OVER(PARTITION BY SCP.[MIN],[ACCOUNT_NUMBER] ORDER BY SCP.[DATE_TIME] DESC) as [Row] FROM
(
SELECT *
FROM [SCPL].[dbo].[SCPL_EOD]
WHERE [SWITCH_RESULT] = 'ANSWERED'
AND [Date] BETWEEN #DateFrom AND #DateTo
) SCP
LEFT JOIN
(
SELECT
SUBSTRING([MIN],2,LEN([MIN])) as [MIN]
,CallID
,[Date]
,ROW_NUMBER() OVER(PARTITION BY [MIN],[PDcampaignBatch] ORDER BY PDTransaction.[SubmittedDateTime] DESC) as [Row]
FROM [Telemarketing].[dbo].[PDTransaction]
WHERE [Date] BETWEEN #DateFrom AND #DateTo
) PDT ON SCP.[MIN] = PDT.MIN AND SCP.[Date] = PDT.[DATE] AND PDT.[Row] = 1
)a
LEFT JOIN [Telemarketing].[dbo].[Disposition] d ON a.CallID = d.[Call ID]
WHERE a.[Row] = 1
) a
WHERE [MIN] =

The format you have is not correct for updating from a derived table, the format would be:
UPDATE A
SET A.Value = B.Value
FROM Table_A AS A
INNER JOIN
(
SELECT B.ID ,
B.Value
FROM Table_B AS B
) AS B ON B.ID = A.ID
WHERE A.ID = 1
But I would suggest using temp tables if that is a possibility, as it makes readability much easier.

Related

Converting SQL view that uses functions to work in snowflake

I have a view in SQL server that i'm trying to convert to work in snowflake. The view uses two functions within it that are called to join onto another table.
I'm following steps provided by another user, but i'm getting lost somewhere in the middle and feel a little stuck.
Here is the query for the SQL Server view:
ALTER VIEW [proj].[pvw_PowerBI_ScrapList]
AS
SELECT
e.Name AS ProductionUnit,
temp.DateTime AS DateTime,
s.Reference AS Shift,
CONVERT(TIME, temp.DateTime) AS Time,
CONVERT(DATE, temp.DateTime - ISNULL((SELECT CAST(MIN(s_first.FromTimeOfDay) AS DateTime) FROM Shift s_first WHERE s_first.FromDay = s.FromDay AND s_first.ShiftCalendarID = s.ShiftCalendarID), CAST('6:00' AS DateTime))) AS ProductionDate,
temp.ScrapReason AS ScrapReason,
temp.Quantity AS ScrapQuantity,
'Manually Registered' AS RegistrationType
FROM (SELECT
CAST(SUM(sreg.ScrapQuantity) AS int) AS Quantity,
sreas.Name As ScrapReason,
DATEADD(MINUTE, 30 * (DATEPART(MINUTE, sreg.ScrapTime) / 30), DATEADD(HOUR, DATEDIFF(HOUR, 0, sreg.ScrapTime), 0)) AS DateTime,
srer.EquipmentID AS EquipmentID
FROM qms.ScrapRegistration sreg WITH (NOLOCK)
INNER JOIN qms.ScrapReason sreas WITH (NOLOCK) ON sreas.ID = sreg.ScrapReasonID -- creating CTE of this table
INNER JOIN WorkRequest wr WITH (NOLOCK) ON wr.ID = sreg.WorkRequestID -- CREATE CTE OF THIS TABLE
INNER JOIN SegmentRequirementEquipmentRequirement srer WITH (NOLOCK) ON srer.SegmentRequirementID = wr.SegmentRequirementID -- CREATE CTE OF THIS TABLE
GROUP BY DATEADD(MINUTE, 30 * (DATEPART(MINUTE, sreg.ScrapTime) / 30), DATEADD(HOUR, DATEDIFF(HOUR, 0, sreg.ScrapTime), 0)), srer.EquipmentID, sreas.Name) temp
INNER JOIN Equipment e WITH (NOLOCK) ON e.ID = temp.EquipmentID -- CREATE CTE OF THIS TABLE
INNER JOIN ShiftCalendar sc WITH (NOLOCK) ON sc.ID = dbo.cfn_GetEquipmentShiftCalendarID(e.ID, temp.DateTime) -- CREATE CTE OF THIS TABLE
INNER JOIN Shift s WITH (NOLOCK) ON s.ID = dbo.cfn_GetShiftIDFromDateTime(temp.DateTime, sc.ID) -- CREATE CTE OF THIS TABLE
UNION
SELECT
e.Name AS ProductionUnit,
temp.DateTime AS DateTime,
s.Reference AS Shift,
CONVERT(TIME, temp.DateTime) AS Time,
CONVERT(DATE, temp.DateTime - ISNULL((SELECT CAST(MIN(s_first.FromTimeOfDay) AS DateTime) FROM Shift s_first WHERE s_first.FromDay = s.FromDay AND s_first.ShiftCalendarID = s.ShiftCalendarID), CAST('6:00' AS DateTime))) AS ProductionDate,
temp.ScrapReason AS ScrapReason,
temp.Quantity AS ScrapQuantity,
'Auto Registered' AS RegistrationType
FROM (SELECT
SUM(ISNULL(asr.ScrapQuantity, 0)) AS Quantity,
sreas.Name As ScrapReason,
DATEADD(MINUTE, 30 * (DATEPART(MINUTE, asr.ScrapTime) / 30), DATEADD(HOUR, DATEDIFF(HOUR, 0, asr.ScrapTime), 0)) AS DateTime,
srer.EquipmentID AS EquipmentID
FROM proj.AutoScrapRegistration asr WITH (NOLOCK)
INNER JOIN qms.ScrapReason sreas WITH (NOLOCK) ON sreas.ID = asr.ScrapReasonID
INNER JOIN WorkRequest wr WITH (NOLOCK) ON wr.ID = asr.WorkRequestID
INNER JOIN SegmentRequirementEquipmentRequirement srer WITH (NOLOCK) ON srer.SegmentRequirementID = wr.SegmentRequirementID
GROUP BY DATEADD(MINUTE, 30 * (DATEPART(MINUTE, asr.ScrapTime) / 30), DATEADD(HOUR, DATEDIFF(HOUR, 0, asr.ScrapTime), 0)), srer.EquipmentID, sreas.Name) temp
INNER JOIN Equipment e WITH (NOLOCK) ON e.ID = temp.EquipmentID
INNER JOIN ShiftCalendar sc WITH (NOLOCK) ON sc.ID = dbo.cfn_GetEquipmentShiftCalendarID(temp.EquipmentID, temp.DateTime) -- the function is called here
INNER JOIN Shift s WITH (NOLOCK) ON s.ID = dbo.cfn_GetShiftIDFromDateTime(temp.DateTime, sc.ID) -- the function is called here
i'm ignoring the union for now to try and get something simply working.
The functions are highlighted in this post How to conver this SQL server Function into a CTE in snowflake
Here is what i have so far:
WITH table_ScrapRegistration (
Quantity
,ScrapReason
,DATETIME
,EquipmentID
,ScrapReasonID
,WorkRequestID
,SegmentRequirementID
)
AS (
SELECT CAST(SUM(sreg.ScrapQuantity) AS INT) AS Quantity
,sreas.Name AS ScrapReason
,DATEADD(MIN, 30 * (DATE_PART(MINUTE, sreg.ScrapTime) / 30)::INT, date_trunc('HOUR', sreg.ScrapTime)) AS DATETIME
,srer.EquipmentID AS EquipmentID
,sreas.ID AS ScrapReasonID
,wr.ID AS WorkRequestID
,srer.SegmentRequirementID AS SegmentRequirementID
FROM DB_BI_DEV.RAW_CPMS_LAG.ScrapRegistration sreg
INNER JOIN DB_BI_DEV.RAW_CPMS_LAG.ScrapReason sreas ON sreas.ID = sreg.ScrapReasonID -- CREATE CTE OF THIS TABLE
INNER JOIN DB_BI_DEV.RAW_CPMS_LAG.WorkRequest wr ON wr.ID = sreg.WorkRequestID -- CREATE CTE OF THIS TABLE
INNER JOIN DB_BI_DEV.RAW_CPMS_LAG.SegmentRequirementEquipmentRequirement srer ON srer.SegmentRequirementID = wr.SegmentRequirementID -- CREATE CTE OF THIS TABLE
GROUP BY DATEADD(MIN, 30 * (DATE_PART(MINUTE, sreg.ScrapTime) / 30)::INT, date_trunc('HOUR', sreg.ScrapTime))
,srer.EquipmentID
,sreas.Name
,sreas.ID
,wr.ID
,srer.SegmentRequirementID
)
,table_scrapreason (
name
,ID
)
AS (
SELECT name
,ID
FROM DB_BI_DEV.RAW_CPMS_LAG.ScrapReason
)
,table_workrequest (
ID
,SegmentRequirementID
) -- this is from a join)
AS (
SELECT id
,SegmentRequirementID
FROM DB_BI_DEV.RAW_CPMS_LAG.WorkRequest
)
,table_SegmentRequirementEquipmentRequirement (
EquipmentID
,SegmentRequirementID
)
AS (
SELECT EquipmentID
,SegmentRequirementID
FROM DB_BI_DEV.RAW_CPMS_LAG.SegmentRequirementEquipmentRequirement
)
,table_equipment (
id
,name
,ParentEquipmentID
,ShiftCalendarEntityNumber
)
AS (
SELECT id
,name
,ParentEquipmentID
,ShiftCalendarEntityNumber
FROM DB_BI_DEV.RAW_CPMS_LAG.Equipment
)
,table_ShiftCalendar (
id,
entitynumber,
begindate,
enddate,
name,
PeriodInDays
)
AS (
SELECT id,
entitynumber,
begindate,
enddate,
name,
PeriodInDays
FROM DB_BI_DEV.RAW_CPMS_LAG.ShiftCalendar)
,table_shift (
ID
,Reference
,FromDay
)
AS -- this is from the temp table
(
SELECT ID
,Reference
,FromDay
FROM DB_BI_DEV.RAW_CPMS_LAG.shift
)
,temp_sub_select
AS (
SELECT sreg.Quantity AS Quantity
,sreas.name AS ScrapReason
,timeadd('minute', TRUNCATE (minute(sreg.DATETIME) / 30) * 30, date_trunc('hour', sreg.DATETIME)) AS DATETIME
,srer.EquipmentID AS EquipmentID
FROM table_ScrapRegistration sreg
INNER JOIN table_scrapreason sreas ON sreas.ID = sreg.ScrapReasonID -- CREATE CTE OF THIS TABLE
INNER JOIN table_workrequest wr ON wr.ID = sreg.WorkRequestID -- CREATE CTE OF THIS TABLE
INNER JOIN table_SegmentRequirementEquipmentRequirement srer ON srer.SegmentRequirementID = wr.SegmentRequirementID -- CREATE CTE OF THIS TABLE
GROUP BY sreg.Quantity
,sreas.name
,timeadd('minute', TRUNCATE (minute(sreg.DATETIME) / 30) * 30, date_trunc('hour', sreg.DATETIME))
,srer.EquipmentID
)
--select * from cte_GetEquipmentShiftCalendarID_part_a
--when i run this i get results
, cte_GetEquipmentShiftCalendarID_part_a
as (
WITH recursive rec_cte(id, parentequipmentid, shiftcalendarentitynumber) AS (
SELECT ID,
ParentEquipmentID,
ShiftCalendarEntityNumber
FROM table_equipment
UNION ALL
SELECT r.ID,
p.ParentEquipmentID,
p.ShiftCalendarEntityNumber
FROM rec_cte AS r
INNER JOIN table_equipment p ON p.ID = r.ParentEquipmentID
AND r.ShiftCalendarEntityNumber IS NULL
)
SELECT c.id,
sc.id AS shiftCalendarID,
sc.begindate,
sc.enddate
FROM rec_cte AS c
LEFT JOIN table_shiftcalendar AS sc ON sc.entitynumber = c.ShiftCalendarEntityNumber
WHERE shiftcalendarentitynumber IS NOT NULL
)
select * from cte_GetEquipmentShiftCalendarID_part_a
-- when i run this, i dont get any results.

Avoid calling twice to the same nested query

I am trying to run this query:
select productID,t.[year]
from (
select ProductID, [year] = year(DT), howMuch = count(*)
from [CONTAINS] as c
join ORDERS as o on c.OrderID = o.OrderID
group by ProductID, year(DT)
) as t
where howMuch >= all (
select howMuch
from (
select ProductID, [year] = year(DT), howMuch = count(*)
from [CONTAINS] as c
join ORDERS as o on c.OrderID = o.OrderID
group by ProductID,year(DT)
) as k
where t.[year] = k.[year]
)
Well, it works. but I want to avoid using the same select query twice. What do you suggest me to do?
It seems your database is SQL Server. If this is the case, you can use a CTE (Common Table Expression), something that was designed for this case.
Your query can be nicely simplified to:
with
q as (
select ProductID, [year]=year(DT),howMuch=count(*)
from [CONTAINS] as c join ORDERS as o on c.OrderID=o.OrderID
group by ProductID,year(DT)
)
select productID, t.[year]
from q as t
where howMuch >= all (
select howMuch from q as k where t.[year]=k.[year]
)

Join Table with a CASE statement and based on the CASE, then SELECT a MAX value

I want to join a table on 4 conditions, of which 2 are very straightforward and 2 other conditions which are more difficult.
The first two:
PMCCONTRACTSTATUS.ContractID = CUSTAMOUNTREPORTTABLE.ContractID
PMCCONTRACTSTATUS.DATAAREAID = CUSTAMOUNTREPORTTABLE.DATAAREAID
The second two:
Only if the FROMDATE from Table PMCCONTRACTSTATUS is lower then the PERIODSTART in Table CUSTAMOUNTREPORTTABLE
AND only if that is the case THEN Take the highest RowNumber. EDIT: Because I want to JOIN the [STATUS] that is the CLOSEST to the PERIODSTART.
EDIT: I Made a sample dataset which only includes the necessary parts to solve the problem.
CREATE TABLE PMCCONTRACTSTATUSLOG2 (
ContractID nvarchar(20)
,[Status] int
,FromDate date
,RowNumber int
);
CREATE TABLE CUSTAMOUNTREPORTTABLE2 (
ContractID nvarchar(20)
,PERIODSTART date
);
INSERT INTO PMCCONTRACTSTATUSLOG2
(ContractID, [Status], FromDate, RowNumber)
VALUES
('HC1','1','01-01-2019','1'),
('HC1','2','01-02-2019','2'),
('HC1','1','01-04-2019','3'),
('HC2','1','01-04-2019','1'),
('HC2','2','01-05-2019','2'),
('HC3','4','01-01-2019','1'),
('HC3','2','01-02-2019','2'),
('HC3','1','01-07-2019','3'),
('HC3','2','01-09-2019','4'),
('HC4','2','01-08-2019','1'),
('HC4','3','01-07-2019','2'),
('HC5','1','01-02-2019','1');
INSERT INTO CUSTAMOUNTREPORTTABLE2
(ContractID, PERIODSTART)
VALUES
('HC1','01-01-2019'),
('HC2','01-01-2019'),
('HC3','01-01-2019'),
('HC5','01-01-2019'),
('HC1','01-02-2019'),
('HC3','01-02-2019'),
('HC5','01-02-2019'),
('HC1','01-03-2019'),
('HC3','01-03-2019'),
('HC5','01-03-2019'),
('HC1','01-04-2019'),
('HC2','01-04-2019'),
('HC3','01-04-2019'),
('HC5','01-04-2019'),
('HC1','01-05-2019'),
('HC2','01-05-2019'),
('HC3','01-05-2019'),
('HC5','01-05-2019');
SELECT * FROM PMCCONTRACTSTATUSLOG2
SELECT * FROM CUSTAMOUNTREPORTTABLE2
I try with the following query to join the PMCCONTRACTSTATUS Table, I know the logic behind the join, but I fail to write a JOIN that combines a CASE WHEN + SELECT statement.
;WITH PMCCONTRACTSTATUS AS
(
SELECT
CONTRACTID
,[STATUS]
,FROMDATE
,DATAAREAID
,ROW_NUMBER() OVER (PARTITION BY CONTRACTID ORDER BY FROMDATE ASC) RN
FROM PMCCONTRACTSTATUSLOG
WHERE [STATUS] <> 10 OR [STATUS] <> 5
)
SELECT
CART.CONTRACTID
,PMCCONTRACTSTATUS.CONTRACTID
,CART.ACCOUNTNUM
,CART.AMOUNTMSTTOTAL
,CART.PERIODSTART
,PMCCONTRACTSTATUS.FROMDATE
,CART.PERIODEND
,CART.NAME
,CART.PMCCONTRACTSTATUSWEIGHTED
,PMCCONTRACTSTATUS.[STATUS]
FROM CUSTAMOUNTREPORTTABLE CART
LEFT JOIN PMCCONTRACTSTATUS
ON PMCCONTRACTSTATUS.CONTRACTID = CART.CONTRACTID
AND PMCCONTRACTSTATUS.DATAAREAID = CART.DATAAREAID
/*AND CASE WHEN PMCCONTRACTSTATUS.FROMDATE <= CART.PERIODSTART
THEN (SELECT MAX(PMCCONTRACTSTATUSLOG.RN) FROM PMCCONTRACTSTATUSLOG)*/
Any suggestions?
This answer is based from my understanding, maybe some parts are missing :
First I try to join with your 3 first conditions in a CTE. And then I create a ROW_NUMBER() based on the DATEDIFF between your 2 dates.
Tell me if it helps :
;WITH
CTE AS (
SELECT
CART.CONTRACTID
,CART.ACCOUNTNUM
,CART.AMOUNTMSTTOTAL
,CART.PERIODSTART
,PMCCONTRACTSTATUSLOG.FROMDATE
,CART.PERIODEND
,CART.NAME
,CART.PMCCONTRACTSTATUSWEIGHTED
,PMCCONTRACTSTATUSLOG.[STATUS]
,ROW_NUMBER() OVER (PARTITION BY CART.CONTRACTID,CART.DATAAREAID ORDER BY DATEDIFF(second,FROMDATE,PERIODSTART) ASC) RN
FROM CUSTAMOUNTREPORTTABLE CART
LEFT JOIN PMCCONTRACTSTATUSLOG
ON PMCCONTRACTSTATUSLOG.CONTRACTID = CART.CONTRACTID
AND PMCCONTRACTSTATUSLOG.DATAAREAID = CART.DATAAREAID
AND PMCCONTRACTSTATUSLOG.FROMDATE <= CART.PERIODSTART
WHERE [STATUS] NOT IN (5,10)
)
SELECT
CONTRACTID
,ACCOUNTNUM
,AMOUNTMSTTOTAL
,PERIODSTART
,FROMDATE
,PERIODEND
,NAME
,PMCCONTRACTSTATUSWEIGHTED
,[STATUS]
FROM CTE
WHERE RN = 1
I believe you should use OUTER APPLY instead of LEFT JOIN
;WITH PMCCONTRACTSTATUS AS
(
SELECT
CONTRACTID
,[STATUS]
,FROMDATE
,DATAAREAID
,ROW_NUMBER() OVER (PARTITION BY CONTRACTID ORDER BY FROMDATE ASC) RN
FROM PMCCONTRACTSTATUSLOG
WHERE [STATUS] <> 10 OR [STATUS] <> 5
)
SELECT
CART.CONTRACTID
,PMCCONTRACTSTATUS.CONTRACTID
,CART.ACCOUNTNUM
,CART.AMOUNTMSTTOTAL
,CART.PERIODSTART
,MAX_PMCCONTRACTSTATUS.FROMDATE
,CART.PERIODEND
,CART.NAME
,CART.PMCCONTRACTSTATUSWEIGHTED
,MAX_PMCCONTRACTSTATUS.[STATUS]
FROM CUSTAMOUNTREPORTTABLE CART
OUTER APPLY (select top 1 *
from PMCCONTRACTSTATUS
where PMCCONTRACTSTATUS.CONTRACTID = CART.CONTRACTID
AND PMCCONTRACTSTATUS.DATAAREAID = CART.DATAAREAID
AND PMCCONTRACTSTATUS.FROMDATE <= CART.PERIODSTART
ORDER BY PMCCONTRACTSTATUSLOG.RN DESC) as MAX_PMCCONTRACTSTATUS

query is not returning distinct record

Hi can you please take a look why my query is not returning distinct record. i want result with following condition OE1='SCHEDCHNG', need only recent records per orderid or ordernum means only one record per ordernum or orderid and also dropdate is null. My query is as below
select DISTINCT TOP 100 OE.ORDERID,OE.ID,OE.ORDERNUM,OE.OE4 from OrderExports OE
inner join (
select ORDERNUM, max(OE4) as MaxDate
from OrderExports
group by ORDERNUM
) tm
on OE.ORDERNUM = tm.ORDERNUM and OE.OE4 = tm.MaxDate
inner join orde_ O on OE.ORDERID = O.ORDERID
WHERE OE1='SCHEDCHNG' AND O.DROPDATE is null
Pretty sparse on details here but I think you are wanting something along these lines.
with SortedResults as
(
select OE.ORDERID
, OE.ID
, OE.ORDERNUM
, OE.OE4
, ROW_NUMBER() over(partition by OE.ORDERID, OE.ORDERNUM order by OE.OE4 desc) as RowNum
from OrderExports OE
inner join
(
select ORDERNUM
, max(OE4) as MaxDate
from OrderExports
group by ORDERNUM
) tm on OE.ORDERNUM = tm.ORDERNUM and OE.OE4 = tm.MaxDate
inner join orde_ O on OE.ORDERID = O.ORDERID
WHERE OE1='SCHEDCHNG'
AND O.DROPDATE is null
)
select ORDERID
, ID
, ORDERNUM
, OE4
from SortedResults
where RowNum = 1
You can try using max and group by as below :
SELECT a.ID, max(a.ORDERID) as OrderID, max(a.ORDERNUM) as OrderNum,MAX(OE.OE4) as OE4 FROM
(
--your query
) a
group by a.ID

Update two columns by another column of next row from same table in sql

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'

Resources