I'm trying to go through a table and update currently null info if there is a previous entry that was not null. The code below is what I came up with but that's just updating every field so that every contact has the same fax number. Does someone who is smarter than me know what to do?
Thanks for the help.
UPDATE dbo.AAASTA_CONTACT
SET
CON_CSN = COALESCE(CRNT_RCD.CON_CSN, LST_RCD.CON_CSN),
CON_COMMENTS = COALESCE(CRNT_RCD.CON_COMMENTS, LST_RCD.CON_COMMENTS),
CON_EMAIL_ADDR = COALESCE(CRNT_RCD.CON_EMAIL_ADDR, LST_RCD.CON_EMAIL_ADDR),
CON_FAX_PH_NUM = COALESCE(CRNT_RCD.CON_FAX_PH_NUM, LST_RCD.CON_FAX_PH_NUM),
CON_HOME_PH_NUM = COALESCE(CRNT_RCD.CON_HOME_PH_NUM, LST_RCD.CON_HOME_PH_NUM),
CON_SEX_MF = COALESCE(CRNT_RCD.CON_SEX_MF, LST_RCD.CON_SEX_MF),
CON_PER_TITLE = COALESCE(CRNT_RCD.CON_PER_TITLE, LST_RCD.CON_PER_TITLE),
CON_WORK_PH_NUM = COALESCE(CRNT_RCD.CON_WORK_PH_NUM, LST_RCD.CON_WORK_PH_NUM),
CON_SUPPRESSMAILFL = COALESCE(CRNT_RCD.CON_SUPPRESSMAILFL, LST_RCD.CON_SUPPRESSMAILFL)
FROM
(
SELECT
CON.ALIAS_KEY,
CON.LAST_UPD,
CON.CON_CSN,
CON.CON_COMMENTS,
CON.CON_EMAIL_ADDR,
CON.CON_FAX_PH_NUM,
CON.CON_HOME_PH_NUM,
CON.CON_SEX_MF,
CON.CON_PER_TITLE,
CON.CON_WORK_PH_NUM,
CON.CON_SUPPRESSMAILFL,
RANK() OVER (PARTITION BY CON.ALIAS_KEY ORDER BY CON.LAST_UPD) AS UPD_RNK
FROM dbo.AAASTA_CONTACT CON
) CRNT_RCD
LEFT OUTER JOIN
(
SELECT
CON.ALIAS_KEY,
CON.LAST_UPD,
CON.CON_CSN,
CON.CON_COMMENTS,
CON.CON_EMAIL_ADDR,
CON.CON_FAX_PH_NUM,
CON.CON_HOME_PH_NUM,
CON.CON_SEX_MF,
CON.CON_PER_TITLE,
CON.CON_WORK_PH_NUM,
CON.CON_SUPPRESSMAILFL,
RANK() OVER (PARTITION BY CON.ALIAS_KEY ORDER BY CON.LAST_UPD) AS UPD_RNK
FROM dbo.AAASTA_CONTACT CON
) LST_RCD
ON CRNT_RCD.ALIAS_KEY = LST_RCD.ALIAS_KEY
WHERE CRNT_RCD.UPD_RNK=1
AND LST_RCD.UPD_RNK>1
Related
Here is the sample data of the two tables , just put together for easy reference
I want the upper part of the table [Outbound].[dbo].[Encounter_Out_P] with column "277CA_FILENAME","277CA_FILENAME2","277CA_FILENAME3","277CA_FILENAME4" as NULLS which are sorted by File_Submitted_DT ascending order to be updated with "277FileId" values of the lower table [Outbound].[dbo].[Encounter_Out_277_P] which are sorted by EDIFECSProcessDate in ascending order. Thanks in advance
Here is my code
WITH
cte_2771 AS (
SELECT
"277CA_FILENAME",
File_Submitted_DT,
TRN02_PatientControlNumber
FROM (
SELECT
I."277CA_FILENAME",
I.File_Submitted_DT,
#cte_277.TRN02_PatientControlNumber
,dense_rank() OVER(PARTITION BY #cte_277.TRN02_PatientControlNumber ORDER BY ABS(DATEDIFF(MINUTE, i.File_Submitted_DT, #cte_277.EDIFECSProcessDate)) ASC) rw1
FROM
[Outbound].[dbo].[Encounter_Out_P] I
INNER JOIN #cte_277 ON I.EncounterID = #cte_277.TRN02_PatientControlNumber
--WHERE EncounterID = 'AP230120920712808806'
)t
WHERE
t.rw1 = 1
)
,
cte_2772 AS (
SELECT
"277FileId"
,1 + ((ROW_NUMBER() OVER(PARTITION BY TRN02_PatientControlNumber ORDER BY EDIFECSProcessDate,File_Submitted_DT ASC ) - 1) % 4)rw2
,TRN02_PatientControlNumber
FROM (
SELECT DISTINCT
p."277FileId",
p.EDIFECSProcessDate,
p.TRN02_PatientControlNumber
,p.ID
,cte_2771.File_Submitted_DT
FROM [Outbound].[dbo].[Encounter_Out_277_P] p
INNER JOIN cte_2771 ON cte_2771.File_Submitted_DT < p.EDIFECSProcessDate
WHERE
p.TRN02_PatientControlNumber = cte_2771.TRN02_PatientControlNumber
) t
)
UPDATE cte_2771
SET "277CA_FILENAME" =
COALESCE(cte_2771."277CA_FILENAME", cte_2772."277FileId" )
FROM cte_2771 INNER JOIN cte_2772
ON cte_2772.TRN02_PatientControlNumber = cte_2771.TRN02_PatientControlNumber
WHERE cte_2772.rw2 = 1
I want the output to be like below, (the upperpart) just put together for easy reference
Notes
I have posted the code for "277CA_FILENAME" only, since it is the same for the rest by changing the WHERE condition changes as "WHERE cte_2772.rw2 = 2,3,4"
if I Uncomment the --WHERE EncounterID = 'AP230120920712808806' in the cte_2771 , it is working perfectly, but if I comment it and run for the entire load, one row gets correct and the other one gets NULL
I am trying to update a SQL table from a remote DB2 table. There may be multiple updates for the same record but I need the updates to happen in the order they are in in the DB2 table. You can not use Order By on a derived table. I have tried several different options to try to get this to work, but the updates still do not happen in order.
For example:
Change 1 - CUSTOMER NAME = ABCX
Change 2 - CUSTOMER NAME = ABC
After I run the query, the customer name is ABCX when it should be ABC.
I truly do not know what else to try. I've tried temp tables (still derived table), creating a concatenated field with date and time fields, sub-select, row_number() over(order by date, time) and many other things. I'd like to keep it in order by the date and time fields in the remote table.
Any insight would be appreciated.
Thank you.
Here is the basic code I have:
SET
A.CUSRID = B.RECORD_ID,
A.CUSSTS = B.ACTIVE_CODE,
A.CUSCOM = B.COMPANY_NUMBER,
A.CUSMNM = B.CUSTOMER_NAME,
A.CUSAD1 = B.CUSTOMER_ADDRESS_1,
A.CUSAD2 = B.CUSTOMER_ADDRESS_2,
A.CUSAD3 = B.CUSTOMER_ADDRESS_3,
A.CUSZIP = B.CUSTOMER_ZIP_CODE,
A.CUSZPE = B.CUSZPE_NOT_USED,
A.CUSSTC = B.CUSTOMER_STATE,
A.CUSARA = B.CUSTOMER_AREA_CODE,
A.CUSPHN = B.CUSTOMER_PHONE,
A.CUSB17 = B.CUSB17_NOT_USED,
A.CUSTMT = B.STATEMENT_PRINT_CODE,
A.CUSCRL = B.CREDIT_LIMIT,
A.CUSCRC = B.CREDIT_CODE,
A.CUSMCD = B.CUSMCD_NOT_USED,
A.CUSTX1 = B.TAX_RATE_1,
A.CUSTX2 = B.TAX_RATE_2,
A.CUSTXC = B.TAX_RATE,
A.CUSTXE = B.TAX_EXEMPT_ID,
A.CUSB48 = B.CUSB48_NOT_USED,
A.CUSMDT = B.MAINTENANCE_DATE,
A.CUSB20 = B.CUSB20_NOT_USED,
A.CSSRCH = B.SEARCH_FIELD,
A.CUSBRN = B.BRANCH_ID,
A.CUSDST = B.DISTRIBUTOR_NUMBER,
A.CUSB28 = B.CUSB28_NOT_USED
FROM
dbo.mcusmas A
INNER JOIN (
SELECT
RECORD_ID,
ACTIVE_CODE,
COMPANY_NUMBER,
CUSTOMER_NUMBER,
CUSTOMER_NAME,
CUSTOMER_ADDRESS_1,
CUSTOMER_ADDRESS_2,
CUSTOMER_ADDRESS_3,
CUSTOMER_ZIP_CODE,
CUSZPE_NOT_USED,
CUSTOMER_STATE,
CUSTOMER_AREA_CODE,
CUSTOMER_PHONE,
CUSB17_NOT_USED,
STATEMENT_PRINT_CODE,
CREDIT_LIMIT,
CREDIT_CODE,
CUSMCD_NOT_USED,
TAX_RATE_1,
TAX_RATE_2,
TAX_RATE,
TAX_EXEMPT_ID,
CUSB48_NOT_USED,
MAINTENANCE_DATE,
CUSB20_NOT_USED,
SEARCH_FIELD,
BRANCH_ID,
DISTRIBUTOR_NUMBER,
CUSB28_NOT_USED,
FROM remoteserver.MCUSMASPLG
WHERE Event_State_ID = '*New' AND SENT_TO_DATA_WAREHOUSE = 'N'
) B
ON A.CUSMNB = B.CUSTOMER_NUMBER
There is no "change 1" or "change 2". There are only rows and SQL Server arbitrarily ends up using one of them. If you want to control the rows, you should select the one you want in advance:
FROM dbo.mcusmas A JOIN
(SELECT B.*,
ROW_NUMBER() OVER (PARTITION BY CUSTOMER_NUMBER ORDER BY <ordering col>) as seqnum
FROM remoteserver.MCUSMASPLG
WHERE Event_State_ID = '*New' AND
SENT_TO_DATA_WAREHOUSE = 'N'
) B
ON A.CUSMNB = B.CUSTOMER_NUMBER
I don't know how you are determining which row is the right one. Presumably, some column has this information and you can use it in the ORDER BY.
select so.nombre + ' ' + so.apellidos as nombre_completo,
se.actividad,
ss.fecha as fecha
from Soldado so, Servicio se, ServicioSoldado ss
where ss.soldadoID = so.soldadoID and ss.servicioID = se.servicioID
group by so.nombre, so.apellidos, se.actividad, ss.fecha, so.soldadoID
order by so.soldadoID, ss.fecha desc
This is the table I have
And this is the output I would like to get:
Try this:
WITH DataSource AS
(
select so.nombre + ' ' + so.apellidos as nombre_completo,
se.actividad,
ss.fecha as fecha,
ROW_NUMBER() OVER (PARTITION BY so.soldadoID ORDER BY ss.fecha desc) AS [RowID]
from Soldado so
INNER JOIN Servicio se
ON so.soldadoID = ss.soldadoID
INNER JOIN ServicioSoldado ss
ON ss.servicioID = se.servicioID
)
SELECT *
FROM DataSource
WHERE [RowID] = 1;
The idea is to use ROW_NUMBER to create an order set of records for each user and the to get the first (the latest) one only for each user.
I have read lots of posts related to the Oracle (11g) error ORA-30926, and I've checked Oracle's documentation on the proper use of the merge statement.
Based on previous threads, I've changed my code to specify a distinct value in the using clause and that is the value I compare in the ON clause. But I still get the ORA-30926 error.
I've also tested the subquery in the USING clause and it returns data without any problem. I've created a temporary table containing only data that meets conditions in the WHERE clause of the USING statement and tried to run that and I still get the error. Both tables have data in them also.
I hope someone can spot something in my code that is incorrect or give me any recommendations on testing.
BEGIN
MERGE
INTO persons myTarget
USING (
select
distinct(USERID),
GIVENNAME,
INITIALS,
SN,
GENERATIONQUALIFIER,
TITLE,
DISPLAYNAME,
TELEPHONENUMBER,
FACSIMILETELEPHONENUMBER,
MOBILE,
OTHERTELEPHONE
from person_updates
WHERE
SN IS NOT NULL
AND LENGTH(SN) < 20
AND SUBSTR(USERID,0,2) IN (SELECT PLACEID FROM code_table)
AND (LENGTH(USERID) = 8 OR LENGTH(USERID) = 10)
) mySource
ON (myTarget.userid = mySource.USERID)
WHEN MATCHED THEN
UPDATE SET myTarget.first_name = UPPER(mySource.GIVENNAME),
myTarget.last_name = UPPER(mySource.SN),
myTarget.generation = UPPER(mySource.GENERATIONQUALIFIER),
myTarget.title = UPPER(mySource.TITLE),
myTarget.display_name = UPPER(mySource.DISPLAYNAME),
myTarget.phone_num = UPPER(mySource.TELEPHONENUMBER),
myTarget.fax_num = UPPER(mySource.FACSIMILETELEPHONENUMBER),
myTarget.mobile_num = UPPER(mySource.MOBILE),
myTarget.dsn_phone = UPPER(mySource.OTHERTELEPHONE);
END;
As correctly told by #shrek using distinct will give you distinct rows across combination of all the columns you have selected. I have used row_number analytical function to get distinct rows only based on userid.
Query:
BEGIN
MERGE
INTO persons myTarget
USING (
select * from(
select
row_number() over(partition by userid order by null) as rn,
USERID,
GIVENNAME,
INITIALS,
SN,
GENERATIONQUALIFIER,
TITLE,
DISPLAYNAME,
EMPLOYEETYPE,
TELEPHONENUMBER,
FACSIMILETELEPHONENUMBER,
MOBILE,
OTHERTELEPHONE
from person_updates
WHERE
SN IS NOT NULL
AND LENGTH(SN) < 20
AND SUBSTR(USERID,0,2) IN (SELECT PLACEID FROM code_table)
AND (LENGTH(USERID) = 8 OR LENGTH(USERID) = 10)) where rn = 1
) mySource
ON (myTarget.userid = mySource.USERID)
WHEN MATCHED THEN
UPDATE SET myTarget.first_name = UPPER(mySource.GIVENNAME),
myTarget.last_name = UPPER(mySource.SN),
myTarget.generation = UPPER(mySource.GENERATIONQUALIFIER),
myTarget.title = UPPER(mySource.TITLE),
myTarget.display_name = UPPER(mySource.DISPLAYNAME),
myTarget.dod_emp_type = UPPER(mySource.EMPLOYEETYPE),
myTarget.phone_num = UPPER(mySource.TELEPHONENUMBER),
myTarget.fax_num = UPPER(mySource.FACSIMILETELEPHONENUMBER),
myTarget.mobile_num = UPPER(mySource.MOBILE),
myTarget.dsn_phone = UPPER(mySource.OTHERTELEPHONE);
END;
Hope this will help.
The first statement is how I have needed to pull a min row based on the org's needs I work for. At first, I would MIN(DATEFIELD) but if someone has two entries on the same day, we had problems. Next I tried MIN(OP__DOCID) where OP__DOCID is the table's unique key. Problem here is if someone ever back-dated an entry they forgot to create, the results would be inaccurate. So, I came up with the below statement. It ensures I get the most recent result from each unique admission.
SELECT OP__DocID
FROM FD__CNSLG_BASIS24 AS PC1
WHERE (OP__DOCID =
(SELECT TOP(1)OP__DocID
FROM FD__CNSLG_BASIS24 AS PC2
WHERE PC2.ClientKey = PC1.Clientkey and PC2.ProgramAdmitKey = PC1.Programadmitkey
ORDER BY Date_Screening
)
)
Recently, I have learned about OVER(PARTITION BY) and have been curious as to the subtle differences in how it works v.s. the statement above, because I do get different result.
SELECT OP__DocID = Min(OP__DOCID) OVER (Partition BY Clientkey, Programadmitkey)
FROM FD__CNSLG_BASIS24
Any insight, or links to other pages I could read would be extremely helpful.
Thanks!
Just use window functions:
select pc.*
from (select pc.*,
row_number() over (partition by Clientkey, ProgramAdmitKey
order by Date_Screening -- do you mean DESC?
) as seqnum
from FD__CNSLG_BASIS24 PC
) pc
where seqnum = 1;
Note: this gets the first record based on the screening date. You might want DESC to get the most recent.
My Solution, for those that were curious
I want to go back and substitute the SELECT TOP(1) for the ROW_Number() function, but I needed to get a report out, and this is providing what I need. Thanks for everyone's help.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
BEGIN
SET NOCOUNT ON;
Declare
#StartDate Date,
#EndDate Date
SET #StartDate = '1/1/2016'
SET #EndDate = '6/1/2016'
WITH CNSL_Clients AS (
SELECT PC_CNT.Clientkey, PC_Cnt.ProgramAdmitKey, PC_Cnt.OP__DOCID
FROM FD__Primary_Client as PC_Cnt
INNER JOIN VW__Cnsl_Session_Count_IndvFamOnly as cnt
ON PC_Cnt.Clientkey = CNT.Clientkey AND PC_Cnt.ProgramAdmitKey = CNT.ProgramAdmitKey
WHERE ((pc_CNT.StartDate between #StartDate AND #EndDate) OR (pc_CNT.StartDate <= #StartDate AND pc_CNT.ENDDate >= #StartDate) OR (pc_CNT.StartDate <= #StartDate AND pc_CNT.ENDDate is null))
AND CNT.SessionCount>=6
),
FIRST_BASIS AS (
SELECT CB24_1.OP__DOCID, CB24_1.Date_Screening, CB24_1.ClientKey, CB24_1.ProgramAdmitKey, CB24_1.Composite_score, CB24_1.Depression_Results,CB24_1.Emotional_Results, CB24_1.Relationships_Results
FROM FD__CNSLG_BASIS24 AS CB24_1
WHERE (CB24_1.OP__DOCID =
(Select TOP(1) CB24_2.OP__DOCID
FROM FD__CNSLG_BASIS24 AS CB24_2
Inner JOIN CNSL_Clients
ON CB24_2.ClientKey = CNSL_Clients.ClientKey AND CB24_2.ProgramAdmitKey = CNSL_Clients.ProgramAdmitKey
WHERE (CB24_1.ClientKey = CB24_2.ClientKey) AND (CB24_1.ProgramAdmitKey = CB24_2.ProgramAdmitKey)
ORDER BY CB24_2.Date_Screening))
),
RECENT_BASIS AS (
SELECT CB24_1.OP__DOCID, CB24_1.Date_Screening, CB24_1.ClientKey, CB24_1.ProgramAdmitKey, CB24_1.Composite_score, CB24_1.Depression_Results,CB24_1.Emotional_Results, CB24_1.Relationships_Results
FROM FD__CNSLG_BASIS24 AS CB24_1
WHERE (CB24_1.OP__DOCID =
(Select TOP(1) CB24_2.OP__DOCID
FROM FD__CNSLG_BASIS24 AS CB24_2
Inner JOIN CNSL_Clients
ON CB24_2.ClientKey = CNSL_Clients.ClientKey AND CB24_2.ProgramAdmitKey = CNSL_Clients.ProgramAdmitKey
WHERE (CB24_1.ClientKey = CB24_2.ClientKey) AND (CB24_1.ProgramAdmitKey = CB24_2.ProgramAdmitKey)
ORDER BY CB24_2.Date_Screening DESC))
)
SELECT F.OP__DOCID AS First_DOCID,R.OP__DOCID as Recent_DOCID,F.ClientKey, F.ProgramAdmitKey, F.Composite_Score AS FComposite_Score, R.Composite_Score as RComposite_Score, Composite_Change = R.Composite_Score - F.Composite_Score, F.Depression_Results AS FDepression_Results, R.Depression_Results AS RDepression_Resluts, Depression_Change = R.Depression_Results - F.Depression_Results, F.Emotional_Results AS FEmotional_Resluts, R.Emotional_Results AS REmotionall_Reslu, Emotional_Change = R.Emotional_Results - F.Emotional_Results, F.Relationships_Results AS FRelationships_Resluts, R.Relationships_Results AS RRelationships_Resluts, Relationship_Change = R.Relationships_Results - F.Relationships_Results
FROM First_basis AS F
FULL Outer JOIN RECENT_BASIS AS R
ON F.ClientKey = R.ClientKey AND F.ProgramAdmitKey = R.ProgramAdmitKey
ORDER BY F.ClientKey
END
GO