Oracle SQL Correlated Subquery (in WHERE statement) having no results - sql

Hi and thanks for reading,
I am trying to run the following SQL query with correlated subquery and it is bringing back no results. I am using the subquery to only bring back results that have the lowest date range. Both the query alone and the subquery alone work fine.
Any ideas? Am I linking the correlated subquery incorrectly?
Note: The correlated subquery is on the last line of the query
Thank you,
Willz06jw
SELECT aaa."effective_time",
aaa."event_type_c",
"clarity_dep"."department_name",
"patient"."birth_date",
"patient"."pat_mrn_id",
"zc_ped_delivr_meth"."name",
"zc_ped_delivr_meth"."ped_delivr_meth_c",
aaa."department_id",
"clarity_dep"."department_id",
aaa."alt_event_type_c",
aaa."in_event_type_c"
FROM (("CLARITY"."clarity_adt" aaa
inner join "CLARITY"."clarity_dep" "CLARITY_DEP"
ON aaa."department_id" = "clarity_dep"."department_id")
inner join "CLARITY"."patient" "PATIENT"
ON aaa."pat_id" = "patient"."pat_id")
inner join "CLARITY"."zc_ped_delivr_meth" "ZC_PED_DELIVR_METH"
ON "patient"."ped_delivr_meth_c" =
"zc_ped_delivr_meth"."ped_delivr_meth_c"
WHERE ( "patient"."birth_date" >= To_date ('01-12-2012 00:00:00',
'DD-MM-YYYY HH24:MI:SS')
AND "patient"."birth_date" < To_date ('06-12-2012 00:00:00',
'DD-MM-YYYY HH24:MI:SS'
) )
AND ( aaa."department_id" = 236601
OR aaa."department_id" = 236703
OR aaa."department_id" = 236801
OR aaa."department_id" = 236901
OR aaa."department_id" = 237101
OR aaa."department_id" = 237201 )
AND aaa."event_type_c" = 3
AND aaa."effective_time" = (SELECT Min(bbb."effective_time")
FROM "clarity_adt" bbb
WHERE aaa."pat_id" = bbb.pat_id)

Without zifting through the entire statement, the easiest solution would be to just wrap the statement in a select using the ROW_NUMBER function to get the lowest dates.
SQL Statement 1
SELECT *
FROM (
SELECT ROW_NUMBER() OVER (PARTITION BY pat_id ORDER BY effective_time) AS rn,
aaa."effective_time",
aaa."event_type_c",
"clarity_dep"."department_name",
"patient"."birth_date",
"patient"."pat_mrn_id",
"zc_ped_delivr_meth"."name",
"zc_ped_delivr_meth"."ped_delivr_meth_c",
aaa."department_id",
"clarity_dep"."department_id",
aaa."alt_event_type_c",
aaa."in_event_type_c"
FROM "CLARITY"."clarity_adt" aaa
inner join "CLARITY"."clarity_dep" "CLARITY_DEP" ON aaa."department_id" = "clarity_dep"."department_id"
inner join "CLARITY"."patient" "PATIENT" ON aaa."pat_id" = "patient"."pat_id"
inner join "CLARITY"."zc_ped_delivr_meth" "ZC_PED_DELIVR_METH" ON "patient"."ped_delivr_meth_c" = "zc_ped_delivr_meth"."ped_delivr_meth_c"
WHERE ( "patient"."birth_date" >= To_date ('01-12-2012 00:00:00', 'DD-MM-YYYY HH24:MI:SS')
AND "patient"."birth_date" < To_date ('06-12-2012 00:00:00', 'DD-MM-YYYY HH24:MI:SS' ) )
AND ( aaa."department_id" = 236601 OR aaa."department_id" = 236703 OR aaa."department_id" = 236801 OR aaa."department_id" = 236901 OR aaa."department_id" = 237101 OR aaa."department_id" = 237201 )
AND aaa."event_type_c" = 3
) q
WHERE q.rn = 1
Your statement could be simplified (in reading it) by using an IN statement io. all the ORstatements like such
SQL Statement 2
SELECT *
FROM (
SELECT ROW_NUMBER() OVER (PARTITION BY pat_id ORDER BY effective_time) AS rn,
aaa."effective_time",
aaa."event_type_c",
"clarity_dep"."department_name",
"patient"."birth_date",
"patient"."pat_mrn_id",
"zc_ped_delivr_meth"."name",
"zc_ped_delivr_meth"."ped_delivr_meth_c",
aaa."department_id",
"clarity_dep"."department_id",
aaa."alt_event_type_c",
aaa."in_event_type_c"
FROM "CLARITY"."clarity_adt" aaa
inner join "CLARITY"."clarity_dep" "CLARITY_DEP" ON aaa."department_id" = "clarity_dep"."department_id"
inner join "CLARITY"."patient" "PATIENT" ON aaa."pat_id" = "patient"."pat_id"
inner join "CLARITY"."zc_ped_delivr_meth" "ZC_PED_DELIVR_METH" ON "patient"."ped_delivr_meth_c" = "zc_ped_delivr_meth"."ped_delivr_meth_c"
WHERE ( "patient"."birth_date" >= To_date ('01-12-2012 00:00:00', 'DD-MM-YYYY HH24:MI:SS')
AND "patient"."birth_date" < To_date ('06-12-2012 00:00:00', 'DD-MM-YYYY HH24:MI:SS' ) )
AND ( aaa."department_id" IN (236601,236703,236801,236901,237101,237201) )
AND aaa."event_type_c" = 3
) q
WHERE q.rn = 1
In the end, I would even simplify it further by aliassing all tables and use a WITH statement. The final result would look like this
SQL Statement 3
;WITH q AS (
SELECT ROW_NUMBER() OVER (PARTITION BY pat_id ORDER BY effective_time) AS rn,
aaa."effective_time",
aaa."event_type_c",
cd."department_name",
p."birth_date",
p."pat_mrn_id",
pdm."name",
pdm."ped_delivr_meth_c",
aaa."department_id",
cd."department_id",
aaa."alt_event_type_c",
aaa."in_event_type_c"
FROM "CLARITY"."clarity_adt" aaa
inner join "CLARITY"."clarity_dep" cd ON aaa."department_id" = cd."department_id"
inner join "CLARITY"."patient" p ON aaa."pat_id" = p."pat_id"
inner join "CLARITY"."zc_ped_delivr_meth" pdm ON p."ped_delivr_meth_c" = pdm."ped_delivr_meth_c"
WHERE p."birth_date" >= To_date ('01-12-2012 00:00:00', 'DD-MM-YYYY HH24:MI:SS'
AND p."birth_date" < To_date ('06-12-2012 00:00:00', 'DD-MM-YYYY HH24:MI:SS' ) )
AND aaa."department_id" IN (236601,236703,236801,236901,237101,237201)
AND aaa."event_type_c" = 3
)
SELECT *
FROM q
WHERE rn = 1

You're only going to get rows if the row with the earliest date also matches the other conditions on clarity_adt. If you want the earliest record for that subset then you'd have to push those conditions into the subquery.

Related

CTE query Not returning any result

The following query works
select TOP 100 T.DWH_ID,T.date_time, T.TimeDiff, T.[End Date], T.SPS_Bereich, T.txtName from (
SELECT sto.[DWH_ID]
,sto.[SPS_Bereich]
,FORMAT(sto.[DateTime], 'dd-MM-yyyy HH:mm') as date_time
,sto.[txtName]
,sto.[TimeDiff]
, DATEADD(second,sto.[TimeDiff],FORMAT(sto.[DateTime], 'dd-MM-yyyy HH:mm'))as [End Date]
FROM [Stoerdaten].[sta].[Stoerungen] sto where sto.Classname='Alarm' and sto.TimeDiff>60 ) as T
join [IgnitionServer].[dbo].[scheduled_events_ISTProduction] cal on
((T.date_time between cal.start_date and cal.end_date) and T.[End Date] between cal.start_date and cal.end_date) where cal.typ=1 order by [DWH_ID] desc
But when I change to CTE it didn't give me any result.
CTE Query
;with q1 as
(
select TOP 1000 [DWH_ID],
SPS_Bereich ,
FORMAT([DateTime], 'dd-MM-yyyy HH:mm') as date_time,
[txtName],
[TimeDiff]
, DATEADD(second,[TimeDiff],FORMAT([DateTime], 'dd-MM-yyyy HH:mm'))as [End_Date]
FROM [Stoerdaten].[sta].[Stoerungen] where Classname='Alarm' and TimeDiff>60
)
select q1.DWH_ID,
q1.date_time,
q1.TimeDiff, q1.[End_Date], q1.txtName, q1.SPS_Bereich from q1 join [IgnitionServer].[dbo].[scheduled_events_ISTProduction] cal on
((q1.date_time between cal.start_date and cal.end_date) and q1.[End_Date] between cal.start_date and cal.end_date) where cal.typ=1
I don't understand what I am missing here. Any help is greatly appreciated.
Your CTE contains the TOP 1000 records in [sta].[Stoerungen] with the WHERE criteria and you then join from that to [scheduled_events_ISTProduction].
In your initial query, you're returning the TOP 100 after the JOIN has been made, so I imagine that whatever is appearing in the result of your CTE can't be joined to the records in [scheduled_events_ISTProduction].
If you just select everything out of your CTE you should see that there are up to 1000 records in there but should also be able to verify the JOIN issue.

Combine 2 sql queries into one with eliminating duplicate colums

I have written 2 sql queries by using multiple join statements.
Now I want to combine both the query results as below.
First query shows these columns
UDC_ID, EXT_ID, VALUE
The second query shows these columns
UDC_ID, EXT_ID, VALUE
In both the queries UDC_ID and EXT_ID columns are the same, but the VALUE column in each is different
So the final output I want to display is,
UDC_ID, EXT_ID, VALUE (From Query1), VALUE (from Query 2)
Can anyone suggest how this can be achieved?
These are my queries:
Query 1 joins three tables:
SELECT
DEV.UDC_ID,
SR.EXT_ID,
SRA.VALUE
FROM SERVICE_REQUEST SR
JOIN DEVICE DEV
ON SR.DEVICE_ID = DEV.ID
JOIN SERVICE_REQUEST_ATTR SRA
ON SR.ID = SERVICE_REQUEST_ID
WHERE SR.SUB_TYPE_CD = 'HMI_22'
--AND DEV.SUB_TYPE = 'ESME'
AND SRA.NAME = 'CommsHubGUID'
AND SR.INSERT_TIME >= TO_DATE('2016-09-21 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
AND SR.INSERT_TIME <= TO_DATE('2016-09-28 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
ORDER BY SR.INSERT_TIME DESC;
The difference between query 1 and this query is the where clause criterion for SRA.NAME field, otherwise both the queries are same.
SELECT
DEV.UDC_ID,
SR.EXT_ID,
SRA.VALUE
FROM SERVICE_REQUEST SR
JOIN DEVICE DEV
ON SR.DEVICE_ID = DEV.ID`enter code here`
JOIN SERVICE_REQUEST_ATTR SRA
ON SR.ID = SERVICE_REQUEST_ID
WHERE SR.SUB_TYPE_CD = 'HMI_22'
--AND DEV.SUB_TYPE = 'ESME'
AND SRA.NAME = 'Service Location'
AND SR.INSERT_TIME >= TO_DATE('2016-09-21 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
AND SR.INSERT_TIME <= TO_DATE('2016-09-28 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
ORDER BY SR.INSERT_TIME DESC
SELECT COALESCE(q1.UDC_ID,q2.UDC_ID),
COALESCE(q1.EXT_ID, q2.EXT_ID),
q1.VALUE ,
q2.VALUE
FROM (query 1) q1
FULL OUTER JOIN (query 2) q2 ON q1.UDC_ID=q2.UDC_ID and q1.EXT_ID=q2.EXT_ID

Convert a nested subquery into normal query

I have problem with following query where in which the nested query should be
converted to normal query:
select
count(*) as count,
TO_CHAR(RH.updated_datetime,'DD-MM-YYYY HH:MI:SS') as date,
SUM(
extract (
epoch from (
RH.updated_datetime - PRI.procedure_performed_datetime
)
)/60
)::integer/count(*) as diff
from
procedure_runtime_information PRI,
study S,
report R,
report_history RH
where
RH.report_fk = R.pk AND
R.study_fk = S.pk AND
S.procedure_runtime_fk = PRI.pk AND
RH.old_status_fk = 21 AND
RH.revision = (select max(revision) from report_history where RH.report_fk = RH.report_fk) AND
RH.updated_datetime > TO_DATE('22-01-2013 00:00:00', 'DD-MM-YYYY HH24:MI:SS') AND RH.updated_datetime < TO_DATE('22-01-2014 00:00:00', 'DD-MM-YYYY HH24:MI:SS')
group by date order by date asc;
Assuming this
(select max(revision) from report_history where RH.report_fk = RH.report_fk)
should really be:
(select max(revision) from report_history x where x.report_fk = RH.report_fk)
You could transform the nested (correlated) subquery into a plain subquery like this (one way of many):
SELECT count(*) AS ct
,to_char(rh.updated_datetime,'DD-MM-YYYY HH:MI:SS') AS date -- HH24?
,sum(extract(epoch FROM (RH.updated_datetime
- PRI.procedure_performed_datetime))
/ 60)::int / count(*) AS diff
FROM procedure_runtime_information PRI
JOIN study S ON S.procedure_runtime_fk = PRI.pk
JOIN report R ON R.study_fk = S.pk
JOIN report_history RH ON RH.report_fk = R.pk
JOIN (
SELECT report_fk, max(revision) AS revision
FROM report_history RH1
GROUP BY 1
) RH1 ON RH1.report_fk = RH.report_fk
AND RH1.revision = RH.revision
WHERE RH.old_status_fk = 21
AND RH.updated_datetime > to_date('22-01-2013', 'DD-MM-YYYY') -- >= ?
AND RH.updated_datetime < to_date('22-01-2014', 'DD-MM-YYYY') -- to_timestamp?
GROUP BY date -- where does date come from?
ORDER BY date;

Sql query for following scenario

I have following scenario, for which i need to write sql query.
I have ICCID table and ICCID property table which holds following information.
I want to find out all active iccids and iccid's which are in removed state in month of december 2012.for ICCIDs which are in removed state, date.to.change key in the ICCID property table itself which record the removed date of ICCID.
this is my attempt, but that did not worked
select e.ID_ICCID from ICCID_PROPERTY e where
e.c_key ='STATE' and e.c_value='Active' or(
e.c_key ='STATE' and
e.c_value='Removed' and
e.c_key='date.to.change' and
to_date(e.c_value,'yyyymmdd') >=to_date('2012-DEC-01 00:00:00', 'YYYY-MON-DD HH24:MI:SS') and
to_date(e.c_value,'yyyymmdd') <= to_date('2012-DEC-31 23:59:59', 'YYYY-MON-DD HH24:MI:SS')
))
Thanks in advance for any help
This is one of the issues with a key-value pair design such as this...
You can't just check a single property row to see if it matches the search criteria, since the criteria in this case will span multiple properties... you have to check if a single parent row has all the children properties that match:
SELECT
i.ICCID
FROM
ICCID i
WHERE
EXISTS (
SELECT 1
FROM ICCID_PROPERTY ip
WHERE
ip.ID_ICCID = i.ID_ICCID
AND ip.c_key = 'STATE'
AND ip.c_value = 'Active'
) OR (
EXISTS (
SELECT 1
FROM ICCID_PROPERTY ip
WHERE
ip.ID_ICCID = i.ID_ICCID
AND ip.c_key = 'STATE'
AND ip.c_value = 'Removed'
) AND
EXISTS (
SELECT 1
FROM ICCID_PROPERTY ip
WHERE
ip.ID_ICCID = i.ID_ICCID
AND ip.c_key = 'date.to.change'
AND to_date(ip.c_value,'yyyymmdd') >=
to_date('2012-DEC-01 00:00:00', 'YYYY-MON-DD HH24:MI:SS')
AND to_date(ip.c_value,'yyyymmdd') <=
to_date('2012-DEC-31 23:59:59', 'YYYY-MON-DD HH24:MI:SS')
)
)
I think you could join the Property table three times -- maybe something like this (untested):
SELECT I.ID_ICCID
FROM ICCID I
JOIN ICCID_Property IP ON I.ID_ICCID = IP.ID_ICCID AND IP.C_Key = 'STATE' AND IP.C_Value = 'Active'
JOIN ICCID_Property IP2 ON I.ID_ICCID = IP.ID_ICCID AND IP2.C_Key = 'STATE' AND IP2.C_Value= 'Removed'
JOIN ICCID_Property IP3 ON I.ID_ICCID = IP.ID_ICCID AND IP3.C_Key = 'date.to.change' AND to_date(IP3.C_Value,'yyyymmdd') >= to_date('2012-DEC-01 00:00:00', 'YYYY-MON-DD HH24:MI:SS')
AND to_date(IP3.C_Value,'yyyymmdd') <=
to_date('2012-DEC-31 23:59:59', 'YYYY-MON-DD HH24:MI:SS')
Good luck.

Converting a correlated sub-query to JOIN

I have a correlated subquery which is creating performance issues. Being a correlated subquery it doesn't accept index hints either. So I am trying to convert it into a JOIN instead. Please find below the original query and the modified query. The modified query doesn't return any row but the original returns me 224 rows.
Appreciate any insight on what is wrong with my JOIN query, if it even makes sense to use JOIN instead of subquery in this case. Thanks.
select Area_CODE,
due_DATE,
RATE,
from SCHED S
where (s.Area_CODE = 11001 and
(s.COMP_CODE = 'a'
or
(s.COMPANY_CODE = 'b'
and s.due_DATE <
(
select
nvl( min(s1.due_DATE), to_date ( '31-DEC-2999', 'DD-MM-YYYY') )
from SCHED s1
where s1.AREA_CODE = s.AREA_CODE
and s1.COMP_CODE = 'c'
)
)
)
)
order by a.EFF_DATE asc, s.due_DATE asc
Modified Query:
SELECT
Area_CODE,
due_DATE,
RATE
from SCHED S
LEFT JOIN
(
SELECT
NVL( MIN(s1.due_DATE), to_date ( '31-DEC-2999', 'DD-MM-YYYY') ) AS
min_date,
s1.AREA_CODE AS a_code
FROM
SCHED s1
WHERE
s1.COMPANY_CODE = 'c'
GROUP BY
s1.AREA_code
)
s2
ON
s2.A_CODE = s.area_code
WHERE
(
s.area_code = 11001
AND
(
s.COMP_CODE = 'a'
OR
(
s.COMP_CODE = 'b'
and s.due_DATE < s2.min_date
)
)
)
order by s.EFF_DATE asc, s.due_DATE asc
The difference is where there are no dates for a given area code
Change the left join (s2) to an inner join on
inner JOIN
(
SELECT
min(s1.due_DATE) AS min_date,
s1.AREA_CODE AS a_code
FROM
(
select Area_Code, due_date from SCHED WHERE COMPANY_CODE = 'c'
union
select Area_Code, to_date('31-dec-2999','DD-MM-YYYY') from SCHED
) s1
GROUP BY
s1.AREA_code
) s2