How to join 2 tables that have the values represented differently in each table? - sql

I currently have 2 tables estimate_details and delivery_service.
estimate_details has a column called event that has events such as: checkout, buildOrder
delivery_service has a column called source that has events such as: makeBasket, buildPurchase
checkout in estimate_details is equivalent to makeBasket in delivery_service, and buildOrder is equivalent to buildPurchase.
estimate_details
id
event
...
1
checkout
...
2
buildOrder
...
delivery_service
id
source
date
...
1
makeBasket
'2022-10-01'
...
2
buildPurchase
'2022-10-02'
...
1
makeBasket
'2022-10-20'
...
I would like to be able to join the tables on the event and source columns where checkout = makeBasket and buildOrder = buildPurchase.
Also if there are multiple records for the specific ID and source in delivery_service , choose the latest one.
How would I be able to do this? I cannot UPDATE either table to have the same values as the other table.
I still want all the data from estimate_details, but would like the latest records from the delivery_service.
The Expected output in this situation would be:
id
event
Date
...
1
checkout
'2022-10-20'
...
2
buildOrder
'2022-10-02'
...

The best approach here is to use a CTE, which is like a subquery but more readable.
So first, in the 'CTE' you will use the delivery_service table to get the max date for each id and source. Then, you will handle the 'text' to manually replace it to make it match that in estimate details
WITH delivery_service_cte AS (
SELECT
id
, CASE
WHEN source = 'makeBasket' THEN 'checkout'
WHEN source = 'buildPurchase' THEN 'buildOrder'
END AS source
, MAX(date) AS date
FROM
delivery_service
GROUP BY
1, 2
)
SELECT
ed.* -- select whichever columns you want from here
, ds.id
, ds.source
, ds.date
FROM
estimate_details ed
LEFT JOIN
-- or JOIN (you didn't give enough info on what you are trying to achieve in
-- the output
delivery_service_cte ds
ON ds.source = ed.event

Related

SQL - Returning fields based on where clause then joining same table to return max value?

I have a table named Ticket Numbers, which (for this example) contain the columns:
Ticket_Number
Assigned_Group
Assigned_Group_Sequence_No
Reported_Date
Each ticket number could contain 4 rows, depending on how many times the ticket changed assigned groups. Some of these rows could contain an assigned group of "Desktop Support," but some may not. Here is an example:
Example of raw data
What I am trying to accomplish is to get the an output that contains any ticket numbers that contain 'Desktop Support', but also the assigned group of the max sequence number. Here is what I am trying to accomplish with SQL:
Queried Data
I'm trying to use SQL with the following query but have no clue what I'm doing wrong:
select ih.incident_number,ih.assigned_group, incident_history2.maxseq, incident_history2.assigned_group
from incident_history_public as ih
left join
(
select max(assigned_group_seq_no) maxseq, incident_number, assigned_group
from incident_history_public
group by incident_number, assigned_group
) incident_history2
on ih.incident_number = incident_history2.incident_number
and ih.assigned_group_seq_no = incident_history2.maxseq
where ih.ASSIGNED_GROUP LIKE '%DS%'
Does anyone know what I am doing wrong?
You might want to create a proper alias for incident_history. e.g.
from incident_history as incident_history1
and
on incident_history1.ticket_number = incident_history2.ticket_number
and incident_history1.assigned_group_seq_no = incident_history2.maxseq
In my humble opinion a first error could be that I don't see any column named "incident_history2.assigned_group".
I would try to use common table expression, to get only ticket number that contains "Desktop_support":
WITH desktop as (
SELECT distinct Ticket_Number
FROM incident_history
WHERE Assigned_Group = "Desktop Support"
),
Than an Inner Join of the result with your inner table to get ticket number and maxSeq, so in a second moment you can get also the "MAXGroup":
WITH tmp AS (
SELECT i2.Ticket_Number, i2.maxseq
FROM desktop D inner join
(SELECT Ticket_number, max(assigned_group_seq_no) as maxseq
FROM incident_history
GROUP BY ticket_number) as i2
ON D.Ticket_Number = i2.Ticket_Number
)
SELECT i.Ticket_Number, i.Assigned_Group as MAX_Group, T.maxseq, i.Reported_Date
FROM tmp T inner join incident_history i
ON T.Ticket_Number = i.Ticket_Number and i.assigned_group_seq_no = T.maxseq
I think there are several different method to resolve this question, but I really hope it's helpful for you!
For more information about Common Table Expression: https://www.essentialsql.com/introduction-common-table-expressions-ctes/

Condensing Data from 4 Columns to 2

I'm trying to combine two sets of columns down to one set in SQL, where all sets have a common JobID and Date.
I want to take columns FrOpr and BkOpr and condense them down to one Opr field while also take their corresponding FrExtract and BkExtract fields down to one corresponding Extract field.
Any thoughts on how to do this?
All the response are much appreciated. I adapted one of the queries below and used it to create a column of data that I wanted to reference and extract from in a larger query.
The output gives me two columns, an Opr and Extract column. In the larger query, I'm looking to select just values from the new Extract column and then Sum them up as a "Completed" output. My problem is knowing where/how to splice/nest this in to the existing query. Any thoughts on how to do this without creating a temp table? I'll post the larger query I want to add this to
SELECT CONCAT(Operators.OprExtID,'CIREG') AS Processor, Convert(VARCHAR(8), Data.StartDateTime, 112) AS [Processed Date], CONCAT('DEPTRI',Machines.EquipmentType,'',JobTypes.JobTypeDesc,'',Jobs.JobName) AS [Activity Type], SUM(Data.Handled) AS Completed FROM dbo.Operators, dbo.Data DataInput, dbo.jobs jobs, dbo.Machines, dbo.JobTypes WITH (nolock) WHERE (Jobs.ID = Data.JobID AND Data.FrOpr = Operators.Operator AND Data.MachNo = Machines.MachNo AND Data.JobTypeID = JobTypes.JobTypeID)
Processor Processed Date Activity Type Completed 0023390_CIREG 20190116 DEPTRI_LWACS_EXTRACTION_UTGENERAL 43.61 0023390_CIREG 20190116 DEPTRI_MWACS_DOC PREP_AGGEN 7.76 0023390_CIREG 20190116 DEPTRI_SWACS_OPENING_UTGENERAL 808 –
Use UNION
SELECT JobId , Date , FrOpr AS Opr , FrExtract AS Extract
FROM< TableName>
WHERE FrOpr IS NOT NULL
UNION ALL
SELECT JobId , Date , BkOpr AS Opr , BkExtract AS Extract
FROM <TableName>
WHERE BkOpr IS NOT NULL
One option is a CROSS APPLY
Example
Select A.JobID
,A.Date
,B.*
From YourTable A
Cross Apply ( values (FrOpr,FrExtract)
,(BkOpr,BKExtract)
) B(Opr,Extract)
Welcome to Stack Overflow! In the future, please provide sample data and desired results in text form.
This is a pretty simple un-pivot, which I'd do with a Union:
Select
JobId
, Date
, FrOpr as Opr
, FrExtract as Extract
, 'Fr' as Source_Column_Set
From <table_name>
Where <whatever conditions your application requires>
Union
Select
JobId
, Date
, BkOpr as Opr
, BkExtract as Extract
, 'Bk' as Source_Column_Set
From <table_name>
Where <whatever conditions your application requires>
You can make that a CTE and sort the results any way you like.
p.s. I included Source_Column_Set to avoid data loss.

Join Table A or Table B in a single query based on some condition

A table has trades info.
The values for grd_market_exchange_cd are mapped to different time_zone_name, which can be obtained by the following ways:
WITH time_zone AS (
SELECT DISTINCT
grd.grd_market_exchange_cd,
ex.time_zone_name
FROM mdm_code.exchange_grd_exchange_map mp
JOIN mdm_code.grd_market_exchange grd ON grd.grd_market_exchange_cd = mp.grd_market_exchange_cd
JOIN mdm.market_exchange ex ON ex.market_exchange_cd = mp.market_exchange_cd
WHERE ex.deactivation_dt IS NULL
AND EXISTS (
SELECT 'X'
FROM ae_os_market_exchange e
WHERE e.market_exchange_cd = ex.market_exchange_cd
AND e.jobs_load_id = ( SELECT MAX(jobs_load_id) FROM ae_os_market_exchange )
)
AND ex.time_zone_name IS NOT NULL
)
SELECT
at.trade_id,
at.trade_execution_tmstmp,
at.grd_market_exchange_cd,
tz.time_zone_name
FROM cd_data.allocated_trade at
JOIN time_zone tz ON tz.grd_market_exchange_cd = at.grd_market_exchange_cd
WHERE TRUNC(TRADE_EXECUTION_TMSTMP) = TRUNC(SYSDATE)
AND TRADE_STATUS_CD IN ('EX','TR')
AND trade_id IN (
308983463,
308983465,
308983929,
308983950,
308979467
);
Option 1:
This is the first way. But the problem in fetching time_zone_name in this way is:
grd_market_exchange_cd is NULL in some cases.
1 grd_market_exchange_cd is mapped to 2 or more time zones in some cases.
grd_market_exchange_cd to time_zone_name mapping is not their for some codes.
We have pick time_zone_name through this way every time, except these three cases mentioned above. As seen above, I get two rows for the same trades if grd_market_exchange_cd
is mapped to 2 time zones or no row if it is NULL or not mapped.
Option 2:
If somehow I don't get time_zone_name by using grd_market_exchange_cd, then I would have to use different tables to fetch the value, as shown below:
SELECT
at.trade_id,
at.trade_execution_tmstmp,
at.grd_market_exchange_cd,
mme.time_zone_name
FROM cd_data.allocated_trade at
JOIN ae_os_listing_v l ON at.tradable_ent_id = l.cde_tradable_entity_id
JOIN ae_os_market_exchange me ON me.listing_key_id = l.listing_key_id
JOIN mdm.market_exchange mme ON me.market_exchange_cd = mme.market_exchange_cd
WHERE TRUNC(trade_execution_tmstmp) = TRUNC(SYSDATE)
AND at.trade_status_cd IN ('EX','TR')
AND me.jobs_load_id = (SELECT MAX(jobs_load_id) FROM ae_os_market_exchange)
AND me.global_exchange_designation_cd = 'P'
AND trade_id IN (
308983463,
308983465,
308983929,
308983950,
308979467
);
I have to develop a single query merging the above two queries so that I pick time_zone_name via Option 1, if grd_market_exchange_cd is mapped to exactly 1 time_zone_name or via Option 2, if I don't obtain a time_zone_name value via Option 1.

Select latest month record from group of records for several groups

I have a table that generates a record each month for each project status report (PSR) if a PSR is/was generated. From a single table, I need to get the most recent record for each PSR.
This gives me the list of PSR's I am looking for:
SELECT Max(Main.PSRMonth) AS MaxOfPSRMonth, Main.PE, Main.Loc, Main.EWO
FROM Main
GROUP BY Main.PE, Main.Loc, Main.EWO
ORDER BY Main.PE, Main.Loc, Main.EWO;
Table:Main
Primary Key is PSRMonth + PE + EWO + LOC
Now, I need all fields FROM Main based on the selection above.
I would like to do this with one SQL statement.
I need all fields FROM Main based on the selection above.
Then try this:
SELECT m1.*
FROM Main m1
INNER JOIN
(
SELECT
Max(PSRMonth) AS MaxOfPSRMonth,
PE,
Loc,
EWO
FROM Main
GROUP BY PE, Loc, EWO
) m2 ON m1.PE = m2.PE AND m1.Loc = m2.Loc AND m1.EWO = m2.EWO
AND m1.PSRMonth = m2.MaxOfPSRMonth
ORDER BY m1.PE, M1.Loc, M1.EWO;

SQL to query by date dependencies

I have a table of patients which has the following columns: patient_id, obs_id, obs_date. Obs_id is the ID of a clinical observation (such as weight reading, blood pressure reading....etc), and obs_date is when that observation was taken. Each patient could have several readings on different dates...etc. Currently I have a query to get all patients that had obs_id = 1 and insert them into a temporary table (has two columns, patient_id, and flag which I set to 0 here):
insert into temp_table (select patient_id, 0 from patients_table
where obs_id = 1 group by patient_id having count(*) >= 1)
I also execute an update statement to set the flag to 1 for all patients that also had obs_id = 5:
UPDATE temp_table SET flag = 1 WHERE EXISTS (
SELECT patient_id FROM patients_table WHERE obs_id = 5 group by patient_id having count(*) >=1
) v WHERE temp_table.patient_id = v.patient_id
Here's my question: How do I modify both queries (without combining them or removing the group by statement) such that I can answer the following question:
"get all patients who had obs_id = 5 after obs_id = 1". If I add a min(obs_date) or max(obs_date) to the select of each query and then add "AND v.obs_date > temp_table.obs_date" to the second one, is that correct??
The reason why I need not remove the group by statement or combine is because these queries are generated by a code generator (from a web app), and i'd like to do that modification without messing up the code generator or re-writing it.
Many thanks in advance,
The advantage of SQL is that it works with sets. You don't need to create temporary tables or get all procedural.
As you describe the problem (find all patients who have obs_id 5 after obs_id 1), I'd start with something like this
select distinct p1.patient_id
from patients_table p1, patients_table p2
where
p1.obs_id = 1 and
p2.obs_id = 5 and
p2.patient_id = p1.patient_id and
p2.obs_date > p1.obs_date
Of course, that doesn't help you deal with your code generator. Sometimes, tools that make things easier can also get in the way.