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

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.

Related

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

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

Join 3 tables complex condition

I have a requirement to join three tables which have the same structure as shown below.
I need to join these tables based on the store and date field values as shown below:
The complex part here is that even if the row in a table does not match with the other tables, it should create a new row with the other values as zero. For example if there is no shipped and allocated quantities for a store on a particular day but if there is a canceled quantity on that day, a new row should be created with shipped $ allocated values set to 0 and cancelled field value set to the correct value. Can anybody suggest the best method to approach this?
this should work
select alldates.procdate,
alldates.store,
st.quantity as ship_quantity,
ct.quantity as cancel_quantity,
at.quantity as allocation_quantity
from (select procdate, store from shp_table union
select procdate, store from cnl_table union
select procdate, store from aloc_table) alldates
left join shp_table st on alldates.procdate = st.procdate and alldates.store = st.store
left join cnl_table ct on alldates.procdate = ct.procdate and alldates.store = ct.store
left join aloc_table at on alldates.procdate = at.procdate and alldates.store = at.store

sql query is not working properly

i am trying to get non matching records from two table by comparing some columns which are common in both tables.i am using sql query to get the result. my first table is snd_marketvisits this table have properties like id ,pjpCode , section code, popCode .pop_name and landmark similary my 2nd table have pjpcode , section code, popcode popname are common and there are some other fields.i want to get the names of the pop which are not in second table but present in snd_marketvisit table by comparing popcode, sectioncode and pjpcode in both tables.
SELECT *
FROM snd_marketvisits sm
LEFT JOIN snd_marketvisit_pops sp ON
sm.distributorCode = sp.distributor AND
sm.pjpCode = sp.pjp AND
sm.sectionCode = sp.sectionCode AND
sm.popCode = sp.popCode
WHERE
sm.sectionCode = '00016' AND
sm.pjpCode = '0001' AND
sm.distributorCode = '00190A'
It depends on the database, as far as I know, but if you ask for NULL inside your yoined fields you should get only the rows without a match.
SELECT *
FROM snd_marketvisits sm
LEFT JOIN snd_marketvisit_pops sp ON
sm.distributorCode = sp.distributor AND
sm.pjpCode = sp.pjp AND
sm.sectionCode = sp.sectionCode AND
sm.popCode = sp.popCode
WHERE
sm.sectionCode = '00016' AND
sm.pjpCode = '0001' AND
sm.distributorCode = '00190A'
AND sp.distributor IS NULL

Left/Right join table with itself

I have a table which contains all the active loans for every month (for example 2017_01, 2017_02, 2017_03, etc). As I don't have another table which contains the Non Active loans (the closed ones) I have to manipulate the same table to get the closed loans for every specific months.
I have tried RIGHT OUTER JOIN in order to get the loans which are part of the previous YEAR_MONTH and have a NULL value in the next month, but as the table is joining itself using the LOAN_NUMBER field as a key, I am not getting the desired results.
Any idea of what I can do?
Ps: In other cases I needed to do that I used the "WHERE NOT EXISTS" clause, but I had two different tables.
My query is:
SELECT DM07MD.LOAN_NUMBER, DM07MD2.LOAN_NUMBER AS L2
FROM [dbo].[DM_07MONTHLY_DATA] DM07MD
LEFT OUTER JOIN [dbo].[DM_07MONTHLY_DATA] DM07MD2
ON DM07MD.LOAN_NUMBER = DM07MD2.LOAN_NUMBER
AND DM07MD.YYYY_MM = '2017_01'
WHERE DM07MD.S90T01_CLIENT_SEGMENT IN ('PI', 'MICRO')
AND DM07MD.S90T01_IS_RESTRUCTURED = 1
AND DM07MD2.LOAN_NUMBER IS NULL
AND DM07MD.YYYY_MM = '2017_02'
You can get the same by using exists,
SELECT DM07MD.LOAN_NUMBER FROM [dbo].[DM_07MONTHLY_DATA] DM07MD where DM07MD.YYYY_MM = '2017_02' and not exists
( SELECT 1 FROM [dbo].[DM_07MONTHLY_DATA] DM07MD2 where DM07MD.YYYY_MM = '2017_01' and DM07MD.LOAN_NUMBER=DM07MD2.LOAN_NUMBER )

Access query inconsistently treats empty string as null

I have an application that is grabbing data from an Access database. I am seeking the minimum value of a column and the results I am getting back are inconsistent.
Have I run into a feature where Access inconsistently treating an empty string as a null depending on whether I add a filter or not, or is there something wrong with the way I am querying the data?
The column contains one blank value (not null) and several non-blank values that are all identical (about 30 instances of 'QLD'). The query I am using has a filter that involves multiple other tables, so that only the blank value and about half of the 'QLD' values are eligible.
It's probably easier to show the code and the effects rather than describe it. I have created a series of unioned queries which 'should' bring back identical results but do not.
Query:
SELECT 'min(LOC_STATE)' as Category
, min(LOC_STATE) as Result
FROM pay_run, pay_run_employee, employee, department, location
WHERE pr_id = pre_prid
AND em_location = loc_id
AND pre_empnum = em_empnum
AND em_department = dm_id
AND pr_date >= #2/24/2015#
AND pr_date <= #2/24/2016#
UNION ALL
(SELECT TOP 1 'top 1 LOC_STATE'
, LOC_STATE
FROM pay_run, pay_run_employee, employee, department, location
WHERE pr_id = pre_prid
AND em_location = loc_id
AND pre_empnum = em_empnum
AND em_department = dm_id
AND pr_date >= #2/24/2015#
AND pr_date <= #2/24/2016#
ORDER BY LOC_STATE)
UNION ALL
SELECT 'min unfiltered', min(loc_state)
FROM location
UNION ALL
(SELECT TOP 1 'iif is null', iif(loc_state is null, 'a', loc_state)
FROM location
ORDER BY loc_state)
Results:
Category Result
min(LOC_STATE) 'QLD'
top 1 LOC_STATE ''
min unfiltered ''
iif is null ''
If I do a minimum with the filter it brings back 'QLD' and not the empty string. At this stage it is possible that the empty string is not being included because it is treated as a null or the filter removes it.
The second query, which brings back the top 1 state using the filter shows that the empty string is not filtered out, which means that the Min function is ignoring the empty string.
The third query, which gets the minimum of the unfiltered table, brings back the empty string - so the minimum function does not exclude empty strings / treat them as null.
The fourth query, ensures that there is not a null in the empty string position.
My conclusion is that perhaps the inclusion of other tables and filter criteria is causing the empty string value to be treated as a null, but I feel that I must be missing something.
NB: I have a very similar query (date literals altered) that executes against the same data imported into a SQL Server database. It is correctly returning '' for all 4 queries.
Does anyone know why the empty string is ignored by the Min function in the first query?
PS: for those who prefer a query with joins
SELECT 'min(LOC_STATE)' as Category
, min(LOC_STATE) as Result
FROM (((pay_run
INNER JOIN pay_run_employee ON pay_run.pr_id = pay_run_employee.pre_prid)
INNER JOIN employee ON pay_run_employee.pre_empnum = employee.em_empnum)
INNER JOIN department ON employee.em_department = department.dm_id)
INNER JOIN location on employee.em_location = location.loc_id
WHERE
PR_DATE >= #2/24/2015# and
PR_DATE <= #2/24/2016#
union all
(SELECT TOP 1 'TOP 1 LOC_STATE'
, LOC_STATE
FROM (((pay_run
INNER JOIN pay_run_employee ON pay_run.pr_id = pay_run_employee.pre_prid)
INNER JOIN employee ON pay_run_employee.pre_empnum = employee.em_empnum)
INNER JOIN department ON employee.em_department = department.dm_id)
INNER JOIN location on employee.em_location = location.loc_id
WHERE
PR_DATE >= #2/24/2015# and
PR_DATE <= #2/24/2016#
order by LOC_STATE)
union all
select 'min unfiltered', min(loc_state)
from location
This has got nothing to do with corrupt data or unions or joins. The problem can be easily made visible by exectuting following queries in access:
create table testbug (Field1 varchar (255) NULL)
insert into testbug (Field1) values ('a')
insert into testbug (Field1) values ('')
insert into testbug (Field1) values ('c')
select min(field1) from testbug
To my opinion this is a bug in ms-access. When the MIN function in ms-access comes across an empty string ('') it forgets all the values he has come across and returns the minimum value from all the values below the empty string. (in my simple example only value 'c')