Merge 3 queries into a single sub query - oracle

Is it possible to write a single query to fetch data from the 3 tables?
Below are the 3 queries that I am running to fetch data, but would need a single query.
I have tried to write the below query but the data I amgetting is wrong
(SELECT M_NB,M_GF_IND,M_HEDGE_LNK FROM TABLE#DATA#DEALCOM_DBF WHERE M_GF_IND = 'Y' ) A
(SELECT M_NB,M_GF_IND,M_HEDGE_LNK FROM TABLE#DATA#DEALIRD_DBF WHERE M_GF_IND = 'Y' ) B
(SELECT M_NB,M_GF_IND,M_HEDGE_LNK FROM TABLE#DATA#DEALSCF_DBF WHERE M_GF_IND = 'Y' ) C
I have tried to write the below query but the data I am getting is wrong
SELECT DD.M_NB, DD.M_GF_IND, DD.M_HEDGE_LNK,
FF.M_NB, FF.M_GF_IND, FF.M_HEDGE_LNK
FROM TABLE#DATA#DEALCOM_DBF DD,
TABLE#DATA#DEALIRD_DBF FF
WHERE DD.M_GF_IND = 'Y' and FF.M_GF_IND = 'Y'
Sorry if this is a bad question, I am new to SQL and thus cannot figure out. Will update if I find any alternative.

Are you looking for UNION (ALL)?
SELECT M_NB,M_GF_IND,M_HEDGE_LNK FROM TABLE#DATA#DEALCOM_DBF WHERE M_GF_IND = 'Y'
UNION ALL
SELECT M_NB,M_GF_IND,M_HEDGE_LNK FROM TABLE#DATA#DEALIRD_DBF WHERE M_GF_IND = 'Y'
UNION ALL
SELECT M_NB,M_GF_IND,M_HEDGE_LNK FROM TABLE#DATA#DEALSCF_DBF WHERE M_GF_IND = 'Y';

Related

Adding filters in subquery from CTE quadruples run time

I am working on an existing query for SSRS report that focuses on aggregated financial aid data split out into 10 aggregations. User wants to be able to select students included in that aggregated data based on new vs. returning and 'selected for verification.' For the new/returning status, I added a CTE to return the earliest admit date for a student. 2 of the 10 data fields are created by a subquery. I have been trying for 3 days to get the subquery to use the CTE fields for a filter, but they won't work. Either they're ignored or I get a 'not a group by expression' error. If I put the join to the CTE within the subquery, the query time jumps from 45 second to 400 seconds. This shouldn't be that complicated! What am I missing? I have added some of the code... 3 of the chunks work - paid_something doesn't.
with stuStatus as
(select
person_uid, min(year_admitted) admit_year
from academic_study
where aid_year between :AidYearStartParameter and :AidYearEndParameter
group by person_uid)
--- above code added to get student information not originally in qry
select
finaid_applicant_status.aid_year
, count(1) as fafsa_cnt --works
, sum( --works
case
when (
package_complete_date is not null
and admit.status is not null
)
then 1
else 0
end
) as admit_and_package
, (select count(*) --does't work
from (
select distinct award_by_aid_year.person_uid
from
award_by_aid_year
where
award_by_aid_year.aid_year = finaid_applicant_status.aid_year
and award_by_aid_year.total_paid_amount > 0 )dta
where
(
(:StudentStatusParameter = 'N' and stuStatus.admit_year = finaid_applicant_status.aid_year)
OR
(:StudentStatusParameter = 'R' and stuStatus.admit_year <> finaid_applicant_status.aid_year)
OR :StudentStatusParameter = '%'
)
)
as paid_something
, sum( --works
case
when exists (
select
1
from
award_by_person abp
where
abp.person_uid = fafsa.person_uid
and abp.aid_year = fafsa.aid_year
and abp.award_paid_amount > 0
) and fafsa.requirement is not null
then 1
else 0
end
) as paid_something_fafsa
from
finaid_applicant_status
join finaid_tracking_requirement fafsa
on finaid_applicant_status.person_uid = fafsa.person_uid
and finaid_applicant_status.aid_year = fafsa.aid_year
and fafsa.requirement = 'FAFSA'
left join finaid_tracking_requirement admit
on finaid_applicant_status.person_uid = admit.person_uid
and finaid_applicant_status.aid_year = admit.aid_year
and admit.requirement = 'ADMIT'
and admit.status in ('M', 'P')
left outer join stuStatus
on finaid_applicant_status.person_uid = stuStatus.person_uid
where
finaid_applicant_status.aid_year between :AidYearStartParameter and :AidYearEndParameter
and (
(:VerifiedParameter = '%') OR
(:VerifiedParameter <> '%' AND finaid_applicant_status.verification_required_ind = :VerifiedParameter)
)
and
(
(:StudentStatusParameter = 'N' and (stuStatus.admit_year IS NULL OR stuStatus.admit_year = finaid_applicant_status.aid_year ))
OR
(:StudentStatusParameter = 'R' and stuStatus.admit_year <> finaid_applicant_status.aid_year)
OR :StudentStatusParameter = '%'
)
group by
finaid_applicant_status.aid_year
order by
finaid_applicant_status.aid_year
Not sure if this helps, but you have something like this:
select aid_year, count(1) c1,
(select count(1)
from (select distinct person_uid
from award_by_aid_year a
where a.aid_year = fas.aid_year))
from finaid_applicant_status fas
group by aid_year;
This query throws ORA-00904 FAS.AID_YEAR invalid identifier. It is because fas.aid_year is nested too deep in subquery.
If you are able to modify your subquery from select count(1) from (select distinct sth from ... where year = fas.year) to select count(distinct sth) from ... where year = fas.year then it has the chance to work.
select aid_year, count(1) c1,
(select count(distinct person_uid)
from award_by_aid_year a
where a.aid_year = fas.aid_year) c2
from finaid_applicant_status fas
group by aid_year
Here is simplified demo showing non-working and working queries. Of course your query is much more complicated, but this is something what you could check.
Also maybe you can use dbfiddle or sqlfiddle to set up some test case? Or show us sample (anonimized) data and required output for them?

Oracle's SDO_CONTAINS not using spatial index on unioned tables?

I'm trying to use Oracle's sdo_contains spatial operator, but it seems, that it's not really working, when you use it on unioned tables.
The below code runs in 2 mins, but you have to duplicate the spatial operator for every source table:
SELECT -- works
x.code,
count(x.my_id) cnt
FROM (select
c.code,
t.my_id
from my_poi_table_1 t,my_shape c
WHERE SDO_contains(c.shape,
sdo_geometry(2001,null,SDO_POINT_type(t.latitude, t.longitude,null),null,null)
) = 'TRUE'
union all
select
c.code,
t.my_id
from my_poi_table_2 t,my_shape c
where SDO_contains(c.shape,
sdo_geometry(2001,null,SDO_POINT_type(t.lat, t.lng,null),null,null)
) = 'TRUE'
) x
group by x.code
I wanted to make it simple, so I tried to first create the points, and then just once use the sdo_contains on it, but it's running for more then 25 mins, because it's not using the spatial index:
SELECT -- does not work
c.code,
count(x.my_id) cnt
FROM my_shape c,
(select
my_id,
sdo_geometry(2001,null,SDO_POINT_type(latitude, longitude,null),null,null) point
from my_poi_table_1 t
union all
select
my_id2,
sdo_geometry(2001,null,SDO_POINT_type(lat, lng,null),null,null) point
from my_poi_table_2 t
) x
WHERE SDO_contains(c.shape,
x.point
) = 'TRUE'
group by c.code
Is there a way to use the sdo_contains on the results of multiple tables without having to include it in the select several times?
Oracle: 12.1.0.2
It seems, that sdo_contains cannot (efficiently) read from a subselect: if I put one of the poi tables into a subselect, then Oracle will not use spatial index for that part:
SELECT -- does not work
x.code,
count(x.my_id) cnt
FROM (select --+ ordered index(c,INDEX_NAME)
c.code,
t.my_id
from my_shape c,(select t.*,rownum rn from my_poi_table_1 t) t
WHERE SDO_contains(c.shape,
sdo_geometry(2001,null,SDO_POINT_type(t.latitude, t.longitude,null),null,null)
) = 'TRUE'
union all
select
c.code,
t.my_id
from my_poi_table_2 t,my_shape c
where SDO_contains(c.shape,
sdo_geometry(2001,null,SDO_POINT_type(t.lat, t.lng,null),null,null)
) = 'TRUE'
) x
group by x.code

Where do I start to optimize this SQL Query?

I have this sql query delivered from a customer which we need to performance optimize.
Is there anyone that can point me in the right direction to where to start looking for optimizing the following query?
The query on my local machine takes about 6-7 seconds, but on the users it´s about 30 seconds, It executes on a mssql 2008r2
Thanks!
var query = #"
DECLARE #SearchString nvarchar(250)
set #SearchString = '1811820001'
;with BaseSelectorCTE (ID) as
(
SELECT ID FROM BaseCases b
where
b.CPR like #SearchString
OR (b.FirstName + ' ' + b.LastName) like #SearchString
OR b.CustomerInfo_InstitutionName like #SearchString
UNION
Select ID from FlexjobCase
where Kommune like #SearchString
UNION
Select ID from DisabledAssistantCase
where Kommune like #SearchString
UNION
Select ID from AdultStudentCase
where Kommune like #SearchString
UNION
Select ID from DiseaseCase
where Kommune like #SearchString
UNION
Select ID from MaternityCase
where Kommune like #SearchString
UNION
Select ID from MiscellaneousCase
where Kommune like #SearchString
UNION
Select ID from WageSubsidyCase
where Kommune like #SearchString
UNION
Select w.ID from WageSubsidyCase w inner join JobCenters j on
w.JobcenterID = j.ID
where
j.Name like #SearchString
UNION
Select a.ID from AdultStudentCase a inner join JobCenters j on
a.JobcenterID = j.ID
where
j.Name like #SearchString
)
--
-- Select BaseCases mapped to result type
--
,ResultSelectorCTE AS
(
select
bc.Id as CaseID,
bc.ChildCaseName,
bc.CPR,
bc.FirstName,
bc.LastName,
bc.CustomerInfo_CustomerInfoID as CustomerInfoID,
bc.CustomerInfo_InstitutionName as InstitutionName,
bc.CaseDeadline,
bc.StatusID,
cs.Name as [StatusName],
cs.Owner as [StatusOwner],
bc.MetaData_Updated as [LastChange],
bc.LastActionDay,
,CASE bc.StatusID WHEN 9 THEN 1 ELSE 0 END as SidstePeriodeSoegt
from BaseCases bc
inner join CaseStatus cs ON
bc.StatusID = cs.ID
inner join BaseSelectorCTE bsCTE ON
bc.ID = bsCTE.ID
)
select * from (Select *, ROW_NUMBER() Over(Order By ##version , CASE WHEN StatusID = 9 then 2 ELSE 1 END, CaseDeadline ASC,
SidstePeriodeSoegt)
As rownum from ResultSelectorCTE where 1=1 AND StatusOwner <> 2 AND StatusOwner <> 3
AND SUBSTRING(CPR, 0, 3) BETWEEN 26-08-2014 AND 26-08-2015) As Result
where rownum Between ((1 - 1) * 100 + 1) AND (1 * 100);
Yes, the query execution plan:
The SQL Server Database Engine can display how it navigates tables and uses indexes to access or process the data for a query or other DML statement, such as an update. This is a display of an execution plan. To analyze a slow-running query, it is useful to examine the query execution plan to determine what is causing the problem.
Without knowing anything, start by losing the wildcards (*) sign. It's bad almost always as you are just saying, send everything and forgetting to actually review it.
Then, format your code correctly, CTE's are great, simplifies code, but it beats the purpose if your selects look like spaghetti, this has nothing to do with performance though.
Also, I had many times when UNION ALL outperformed UNION and I din't really think if duplicates were a problem or not, so you might want to look into that.
You didn't say if you are running it from Management Studio, are you on a local or remote server, how do the CTE's perform individually, etc. Context is king on this.
Hope this helps.

Exists query with not equal running extremly slow

I am trying to modify a query that someone else wrote which is taking a really long time to run. The problem has to do with the <> portion of the exists query. Any idea how this can be changed to run quicker?
SELECT m.level4 center, cc.description, m.employeename, m.empno,
TO_DATE (ct.tsdate, 'dd-mon-yyyy') tsdate, ct.starttime, ct.endtime,
ct.DURATION,
NVL (DECODE (ct.paycode, ' ', 'REG', ct.paycode), 'REG') paycode,
ct.titlecode, ct.costcenter, m.tsgroup
FROM clairvia_text ct, MASTER m, costcenteroutbound cc
WHERE ct.recordtype = '1'
AND ct.empno = m.empno
AND m.level4 = cc.center
AND EXISTS (
SELECT ct1.recordtype,ct1.empno,ct1.tsdate,ct1.processdate
FROM clairvia_text ct1
WHERE ct.recordtype = ct1.recordtype
AND ct.empno = ct1.empno
AND ct.tsdate = ct1.tsdate
AND ct.processdate = ct1.processdate
group by ct1.recordtype,ct1.empno,ct1.tsdate,ct1.processdate
having count(*) < 2)
Oracle can be finnicky with exists statements and subqueries. A couple of things to try:
Change the exists to an "in"
Change the exists to a group by statement with a "having count(1) > 1". This could even be changed into a join.
I'm assuming indexes are not an issue.
You can use analytic function count here to eliminate duplicated rows.
select * from (
SELECT m.level4 center, cc.description, m.employeename, m.empno,
TO_DATE (ct.tsdate, 'dd-mon-yyyy') tsdate, ct.starttime, ct.endtime,
ct.DURATION,
NVL (DECODE (ct.paycode, ' ', 'REG', ct.paycode), 'REG') paycode,
ct.titlecode, ct.costcenter, m.tsgroup,
count(1) over (partition by ct.recordtype,ct.empno,ct.tsdate,ct.processdate
order by null) cnt
FROM clairvia_text ct, MASTER m, costcenteroutbound cc
WHERE ct.recordtype = '1'
AND ct.empno = m.empno
AND m.level4 = cc.center
) where cnt=1
I do not have your structures and data, so I run similar queries with all_tab_cols and first query took ~500s on my laptop and second query ~2s.
-- slow test
select count(1)
from all_tab_cols atc
where exists (
select 1
from all_tab_cols atc1
where atc1.column_name = atc.column_name
group by column_name
having count(1) = 1)
-- fast test
select count(1)
from (
select column_name,
count(1) over (partition by atc.column_name order by null) cnt
from all_tab_cols atc
)
where cnt = 1

Using a table alias in a case statement in a where clause

I have the following query:
Select emp_id, emp_name, department, salary
from tbl_employee emp
where (
CASE
when emp.department = 'C'
then (select count(*) from (SELECT 'Y' iscommissioner
FROM tbl_emp_department ted
where ted.department = emp.department ))
when emp.department = 'C'
then (select count(*) from (SELECT 'Y' iscommissioner
FROM tbl_emp_department ted
where ted.department = emp.department
and ted.id = 7))
END) > 0
I am getting the following error:
emp.department invalid identifier
What am I doing wrong? Why can't I access that column with a table alias in the where clause in a case statement?
Any idea?
This has nothing to do with the case statement. The issue is the scoping rules for correlated subqueries. They only nest one level deep. Here is another question with this problem.
For your example, you don't need nested subqueries. You can just do:
where (CASE when emp.department = 'C'
then (select count(*)
from tbl_emp_department ted
where ted.department = emp.department
)
when emp.department = 'C'
then (select count(*)
from tbl_emp_department ted
where ted.department = emp.department and ted.id = 7
)
END) > 0
However, because your query doesn't really make sense (the same conditions for the two when clauses, I suspect that your actual query may be more complicated. You may have to find another approach to do what you want, using explicit joins and aggregations or using analytic functions.

Resources