Please help combining with clause scans into one - oracle

I have this query below that runs in acceptable time, however was questioned if it could be improved by eliminating aggregation scans (combining 'prv' and 'nxt' "with clause" scans into one), however am unable to find how to actually do it....
any help would be appreciated
With mtype as (
SELECT c.old_type, c.old_type_id, a.magazine_id, a.publ_date
FROM news.magazines a,
news.categories c
WHERE a.category_id = c.category_id
AND a.magazine_id = v_magazine_id
AND a.status_id = 6
AND a.pull_flag = 'Y')
,nxt as (
SELECT m.magazine_id original_id,
MAX(a.magazine_id) KEEP (DENSE_RANK FIRST ORDER BY a.publ_date) AS next_magazine_id,
MAX(a.old_magazine_id) KEEP (DENSE_RANK FIRST ORDER BY a.publ_date) AS next_old_magazine_id,
MAX(a.subject) KEEP (DENSE_RANK FIRST ORDER BY a.publ_date) AS next_subject,
MAX(DECODE(i.active_flag,'N',NULL,i.image_name) ) KEEP (DENSE_RANK FIRST ORDER BY a.publ_date) AS next_image_name,
MAX(DECODE(i.active_flag,'N',NULL,i.meta_image) ) KEEP (DENSE_RANK FIRST ORDER BY a.publ_date) AS next_meta_image
FROM news.magazines a,
news.magazine_images i,
news.categories c,
mtype m
WHERE a.magazine_id = i.magazine_id(+)
AND a.category_id = c.category_id
AND c.old_type_id = m.old_type_id
AND c.old_type = m.old_type
AND a.old_magazine_id IS NOT NULL
AND a.publ_date > m.publ_date
group by m.magazine_id)
,prv as
(
SELECT m.magazine_id original_id,
MAX(a.magazine_id) KEEP (DENSE_RANK FIRST ORDER BY a.publ_date DESC) AS prev_magazine_id,
MAX(a.old_magazine_id) KEEP (DENSE_RANK FIRST ORDER BY a.publ_date DESC) AS prev_old_magazine_id,
MAX(a.subject) KEEP (DENSE_RANK FIRST ORDER BY a.publ_date DESC) AS prev_subject,
MAX(DECODE(i.active_flag,'N',NULL,i.image_name) ) KEEP (DENSE_RANK FIRST ORDER BY a.publ_date DESC) AS prev_image_name,
MAX(DECODE(i.active_flag,'N',NULL,i.meta_image) ) KEEP (DENSE_RANK FIRST ORDER BY a.publ_date DESC) AS prev_meta_image
FROM news.magazines a,
news.magazine_images i,
news.categories c,
mtype m
WHERE a.magazine_id = i.magazine_id(+)
AND a.category_id = c.category_id
AND c.old_type_id = m.old_type_id
AND c.old_type = m.old_type
AND a.old_magazine_id IS NOT NULL
AND a.publ_date < m.publ_date
group by m.magazine_id)
SELECT a.magazine_id, prev_magazine_id, next_magazine_id, a.category_id, c.automated_category, c.old_type_id,
TO_CHAR(a.publ_date,'MM/DD/YYYY HH24:MI:SS') publ_date,
TO_CHAR(a.created_on,'MM/DD/YYYY HH24:MI:SS') created_on,
s.status_id, s.status_text, c.follow_ind, v.channel_id, v.media_id, c.category_name,
CASE
WHEN c.old_type = 'B' THEN a.author_blog_id
WHEN c.old_type = 'C' THEN a.author_comm_id
ELSE a.author_id
END AS author_id, a.author_name, a.image_file_name,
a.author_id owner_id, a.display_author, c.dc_page_id,
TO_CHAR(a.ex_publ_date,'MM/DD/YYYY HH24:MI:SS') ex_publ_date,
a.old_magazine_id, prev_old_magazine_id, next_old_magazine_id,
DECODE(i.active_flag,'N',NULL,i.image_name) image_name, prev_image_name, next_image_name,
subject, prev_subject, next_subject, a.media_items, i.meta_image, prev_meta_image, next_meta_image,
d.image_name AS copyright_image_name, DECODE(UPPER(d.copyright),'OTHER',image_source,d.copyright) copyright,
d.date_uploaded AS copyright_date_uploaded, d.user_name AS copyright_user_name, d.image_source,
a.seo_keywords, a.seo_title_tag, a.seo_description, a.url_body_id, a.teaser_message,
(SELECT first_name || ' ' || last_name FROM news.users WHERE user_id = a.orig_author_id) orig_author_name,
(SELECT count(*) FROM news.user_comments u WHERE u.magazine_id = a.magazine_id) total_comments,
ati.ticker_string AS ticker_data,
ata.tag_string AS tag_data,
ai.image_string AS image_data
FROM news.magazines a,
news.status s,
news.video v,
news.magazine_images i,
news.categories c,
news.copyright_image_data d,
news.magazine_tickers_collected ati,
news.magazine_tags_collected ata,
news.magazine_images_collected ai, nxt x, prv y
WHERE
a.magazine_id = x.original_id(+)
AND a.magazine_id = y.original_id(+)
AND a.status_id = s.status_id
AND a.category_id = c.category_id
AND a.magazine_id = v.magazine_id(+)
AND a.magazine_id = i.magazine_id(+)
AND a.magazine_id = ata.magazine_id(+)
AND a.magazine_id = ati.magazine_id(+)
AND a.magazine_id = ai.magazine_id(+)
AND i.copyright_image_id = d.image_id(+)
and exists ( select 1 from mtype m where a.magazine_id = m.magazine_id);
Since only difference in where clause is ( a.publ_date > m.publ_date vs a.publ_date < m.publ_date ) and dense_rank order
I tried removing the aforementioned condition from where clause combine two queries into one using
something like:
max(case when A.PUBL_DATE > M.PUBL_DATE then A.magazine_ID end ) KEEP (DENSE_RANK FIRST ORDER BY A.PUBL_DATE) AS NEXT_magazine_ID,
however that did not produce expected results. What would be other ways to possibly make that work?
Thank you.

You can put the join conditions from NXT and PRV together in a separate common table expression and then use a CASE expression to separate them later. Although this change actually creates more common table expressions, it stops the code from repeating itself, which is the real reason behind common table expressions.
...
,next_or_prev as
(
SELECT m.magazine_id original_id, a.publ_date,
CASE WHEN a.publ_date > m.publ_date THEN 'NEXT' ELSE 'PREV' END is_next_or_prev
FROM ...
WHERE ...
--Include both less than and greater than predicates in one.
AND a.publ_date <> m.publ_date
...
)
,nxt as
(
SELECT m.magazine_id original_id,
MAX(a.magazine_id) KEEP (DENSE_RANK FIRST ORDER BY a.publ_date) AS next_magazine_id,
... NEXT_ columns here ...
FROM next_or_prev
WHERE is_next_or_prev = 'NEXT'
GROUP BY ...
)
,prv as
(
SELECT m.magazine_id original_id,
MAX(a.magazine_id) KEEP (DENSE_RANK FIRST ORDER BY a.publ_date DESC) AS prev_magazine_id,
... PREV_ columns here ...
FROM next_or_prev
WHERE is_next_or_prev = 'PREV'
GROUP BY ...
)
...
(SELECT * FROM nxt) x,
(SELECT * FROM prv) y,
...

Related

procedure failurecompilation

I have an existing procedure which creates a table adwstg.switchhold_notificatn_stg
Suddenly it is throwing error in creating the table. I didn't change anything the statement.
First I thought the error is with ''No'' . So find & replace '' with '
But it is throwing error at line:
nvl(ba300_z51.sent_650_01, 'No') sent_650_01,
error(27,29): PLS-00103: Encountered the symbol "NO" when expecting one of the following: * & = - + ; < / > at in is mod remainder not rem <> or != or ~= >= <= <> and or like like2 like4 likec between || multiset member submultiset***
Below is the query :
create table adwstg.switchhold_notificatn_stg nologging parallel (degree 8) compress as
select distinct
bad3700.createdon,
bad3700.uc_pod_ext,
bpc.cacont_acc,
bad3700.notificatn,
bad3700.nfcat_code,
nvl(ba300_z51.sent_650_01, ''No'') sent_650_01,
decode(ba300_z51.sent_650_01,''No'',''--'',''Yes'',to_char(ba300_z51.ucswmsgdat,''yyyymmdd''),''--'') date_sent_650_01,
nvl(to_char(ba300_z51.ucswmsgtim,''hh24:mi:ss''),''--'') time_sent_650_01,
nvl(ba300_z52.received_650_02, ''No'') received_650_02,
decode(ba300_z52.received_650_02,''No'',''--'',''Yes'',to_char(ba300_z52.ucswmsgdat,''yyyymmdd''),''--'') date_received_650_02,
nvl(to_char(ba300_z52.ucswmsgtim,''hh24:mi:ss''),''--'') time_received_650_02,
nvl(ba300_z20.received_814_20, ''No'') received_814_20,
decode(ba300_z20.received_814_20,''No'',''--'',''Yes'',to_char(ba300_z20.ucswmsgdat,''yyyymmdd''),''--'') date_received_814_20,
nvl(to_char(ba300_z20.ucswmsgtim,''hh24:mi:ss''),''--'') time_received_814_20,
case
when trim(bad3700.nfcat_code) = ''SH01'' and zet.ext_ui is not null then ''ADDED''
when trim(bad3700.nfcat_code) = ''SH01'' and zet.ext_ui is null then ''NOT PROCESSED''
when trim(bad3700.nfcat_code) in (''SH02'',''SH03'') and zet.ext_ui is null then ''REMOVED''
when trim(bad3700.nfcat_code) in (''SH02'',''SH03'') and zet.ext_ui is not null then ''NOT PROCESSED''
else ''NOT PROCESSED''
end work_order_check
from
(select distinct *
from
(select
trunc(createdon) createdon,
trim(notificatn) notificatn,
trim(uc_pod_ext) uc_pod_ext,
trim(not_type) not_type,
trim(nfcat_code) nfcat_code,
row_number () over (partition by trim(uc_pod_ext),trunc(createdon) order by trim(notificatn) desc) rnum
from birpt.bic_azfc_ds3700
where upper(trim(not_type)) = ''SH''
and trim(bic_zdiscstat) = ''E0010'')
where rnum = 1
) bad3700
left outer join
(
select distinct ucinstalla, uc_pod_ext, datefrom, dateto
from birpt.bi0_qucinstalla
where objvers = ''A''
) bqi
on (trim(bad3700.uc_pod_ext) = trim(bqi.uc_pod_ext)
and trunc(bad3700.createdon) between bqi.datefrom and bqi.dateto)
left outer join
(
select distinct cacont_acc, ucinstalla, ucmovein_d, ucmoveoutd
from birpt.bi0_puccontract
where objvers = ''A''
) bpc
on (trim(bqi.ucinstalla) = trim(bpc.ucinstalla)
and trunc(bad3700.createdon) between bpc.ucmovein_d and bpc.ucmoveoutd)
left outer join
(select distinct *
from
(select
trim(ucswtpodex) ucswtpodex,
trunc(ucswmsgdat) ucswmsgdat,
ucswmsgtim,
case --650_01 CHECK
when trim(uc_mdcat) = ''Z51'' then ''Yes''
else ''No''
end sent_650_01,
row_number () over (partition by trim(ucswtpodex), trunc(ucswmsgdat) order by trunc(ucswmsgdat) desc, ucswmsgtim desc) rnum
from birpt.bic_azudeds0300
where trim(uc_mdcat) = ''Z51'')
where rnum = 1) ba300_z51
on (trim(bad3700.uc_pod_ext) = trim(ba300_z51.ucswtpodex)
and trunc(bad3700.createdon)= trunc(ba300_z51.ucswmsgdat))
left outer join
(select distinct *
from
(select
trim(ucswtpodex) ucswtpodex,
trunc(ucswmsgdat) ucswmsgdat,
ucswmsgtim,
case --650_02 CHECK
when trim(uc_mdcat) = ''Z52'' then ''Yes''
else ''No''
end received_650_02,
row_number () over (partition by trim(ucswtpodex), trunc(ucswmsgdat) order by trunc(ucswmsgdat) desc, ucswmsgtim desc) rnum
from birpt.bic_azudeds0300
where trim(uc_mdcat) = ''Z52'')
where rnum = 1) ba300_z52
on (trim(bad3700.uc_pod_ext) = trim(ba300_z52.ucswtpodex)
and trunc(bad3700.createdon)= trunc(ba300_z52.ucswmsgdat))
left outer join
(select distinct *
from
(select
trim(ucswtpodex) ucswtpodex,
trunc(ucswmsgdat) ucswmsgdat,
ucswmsgtim,
case --814_20 CHECK
when trim(uc_mdcat) = ''Z20'' then ''Yes''
else ''No''
end received_814_20,
row_number () over (partition by trim(ucswtpodex), trunc(ucswmsgdat) order by trunc(ucswmsgdat) desc, ucswmsgtim desc) rnum
from birpt.bic_azudeds0300
where trim(uc_mdcat) = ''Z20'')
where rnum = 1) ba300_z20
on (trim(bad3700.uc_pod_ext) = trim(ba300_z20.ucswtpodex)
and trunc(bad3700.createdon)= trunc(ba300_z20.ucswmsgdat))
left outer join
(select distinct ext_ui
from isurpt.zcs_esiid_tamper
) zet
on (trim(bad3700.uc_pod_ext) = trim(zet.ext_ui));
If you remove all doubled single quotes (perform replace function in any text editor), your code will be valid (as far as syntax is concerned).
I don't have your tables to test it, and there are too many of them with too many columns to create a test case by myself.
The question is: why did you double them in the first place?

WITH Clause no longer working. "exceeded call limit on IO usage"

I have some code that previously ran fine with no issues. But now when I run I receive the
ORA-02395: exceeded call limit on IO usage
02395. 00000 - "exceeded call limit on IO usage"
error. Can anyone explain to me why my code is throwing this error. I have no access to increase any user privileges. I've tried running this code and limiting the amount of data in the with clause and it ran fine. So I'm guessing some modifications need to happen there.
WITH NEW_REP_DATA AS (
select period,manager rep,comp,sum(a) "GT99",sum(b) "90TO99",sum(c) "80TO89",sum(d) "70TO79",sum(e) "LT70",sum(f) "NA" from (
select period
,rep_code
,manager
--,nvl(a,0)+nvl(b,0)+nvl(c,0)+nvl(d,0)+nvl(e,0)+nvl(f,0) cnt
,comp,
nvl(a,0) a,nvl(b,0) b, nvl(c,0) c, nvl(d,0) d,nvl(e,0) e,nvl(f,0) f
from
(select period,rep_code,manager, comp,max(case when bucket='>99' then cnt end) a,
max(case when bucket='90TO99' then cnt end) b,
max(case when bucket='80TO89' then cnt end) c,
max(case when bucket= '70TO79' then cnt end) d,
max(case when bucket='LT70' then cnt end) e,
max(case when bucket='NA' then cnt end) f
from (
select period,rep_code,manager, comp,bucket,
--count(unique rep_code)
count( distinct rep_code) cnt
--cnt
from(
select * from (select
unique period
,MANAGER
,"PayeeID" rep_code
,comp
,cytd cytd_a
,cytp cytd_p,
nvl(case when cytp > 0 then
case when round((cytd/cytp),3) > .99 then '>99'
when round((cytd/cytp),3) between .891 and .99 then '90TO99'
when round((cytd/cytp),3) between .791 and .89 then '80TO89'
when round((cytd/cytp),3) between .7 and .79 then '70TO79'
when round((cytd/cytp),3) < .7 then 'LT70'
end
when cytp = 0 and cytd > 0 then '>99'
else 'NA'
end,'NA') as bucket
from (
select aaa.period
,aaa."PayeeID"
,aaa."Reports_to" MANAGER
,aaa."Component" comp,
aaa."Current_YTD_Actual" cytd,
aaa."Current_YTD_Plan" cytp
from nbr_var_data aaa
where aaa."Comp_Plan_Name" not in ('MISC_COMP','GM_2017')
AND "Comp_Plan_Name" not in ('MISC_COMP')
AND "Comp_Plan_Name" not LIKE '%GM%'
and aaa.period = (select max(aaa.period) from Nbr_Var_Data)
))
)
where 1=1
group by period, rep_code, comp, bucket, manager )
group by period, rep_code, comp, manager )) group by period, manager, comp)
SELECT DISTINCT
dc.rep PID
,dc.period
,ee.PAYEE_NAM
,dc.comp
,Dc."GT99"
,Dc."90TO99"
,Dc."80TO89"
,Dc."70TO79"
,Dc."LT70"
,Dc."NA"
,Ee.Parent_Payee_Id REPORT_TO_PAYEE_ID
,Ee.Parent_Payee_Nam REPORT_TO_NAME
FROM (SELECT
--period ,
--empl_id ,
gg.payee_id ,
gg.payee_nam ,
--lvl ,
ff.parent_payee_id ,
ff.PARENT_PAYEE_NAM
--parent_lvl ,
--mnth_disp
FROM (SELECT DISTINCT
dd.period
,dd.PARENT_PAYEE_ID
,ee.PAYEE_NAM PARENT_PAYEE_NAM
from (
SELECT DISTINCT
PERIOD,
PARENT_PAYEE_ID
FROM FI_CHANNEL_HIER) dd
left join FI_CHANNEL_HIER ee
on dd.PARENT_PAYEE_ID = ee.PAYEE_ID
WHERE DD.PERIOD = (select max(DD.PERIOD) from FI_CHANNEL_HIER )) ff
LEFT JOIN FI_CHANNEL_HIER gg
ON ff.PARENT_PAYEE_ID = gg.PARENT_PAYEE_ID) ee,
NEW_REP_DATA dc
WHERE EE.PAYEE_ID = DC.Rep
;
ORA-02395 happens when your query exceeds the LOGICAL_READS_PER_CALL threshold set in your user profile. That's why the issue goes away when you restricted the amount of data returned by your subquery.
Two possible explanations for why this did not use to happen:
The tables contain more data than they used to be.
Your DBA has implemented a new user profile (or made the existing one stricter).
The obvious solution is to negotiate with the DBA.
Otherwise you will need to refactor your query to reduce the number of blocks it scans. Doing requires an understanding of your data model, your business logic and your data characteristics (volume, distribution, usage).
Clearly that requires knowledge of and access to your system, so it's not something that we can help with.
WITH NEW_REP_DATA AS (
select period,manager rep,comp,sum(a) "GT99",sum(b) "90TO99",sum(c) "80TO89",sum(d) "70TO79",sum(e) "LT70",sum(f) "NA" from (
select period
,rep_code
,manager
--,nvl(a,0)+nvl(b,0)+nvl(c,0)+nvl(d,0)+nvl(e,0)+nvl(f,0) cnt
,comp,
nvl(a,0) a,nvl(b,0) b, nvl(c,0) c, nvl(d,0) d,nvl(e,0) e,nvl(f,0) f
from
(select period,rep_code,manager, comp,max(case when bucket='>99' then cnt end) a,
max(case when bucket='90TO99' then cnt end) b,
max(case when bucket='80TO89' then cnt end) c,
max(case when bucket= '70TO79' then cnt end) d,
max(case when bucket='LT70' then cnt end) e,
max(case when bucket='NA' then cnt end) f
from (
select period,rep_code,manager, comp,bucket,
--count(unique rep_code)
count( distinct rep_code) cnt
--cnt
from(
select * from (select
unique period
,MANAGER
,"PayeeID" rep_code
,comp
,cytd cytd_a
,cytp cytd_p,
nvl(case when cytp > 0 then
case when round((cytd/cytp),3) > .99 then '>99'
when round((cytd/cytp),3) between .891 and .99 then '90TO99'
when round((cytd/cytp),3) between .791 and .89 then '80TO89'
when round((cytd/cytp),3) between .7 and .79 then '70TO79'
when round((cytd/cytp),3) < .7 then 'LT70'
end
when cytp = 0 and cytd > 0 then '>99'
else 'NA'
end,'NA') as bucket
from (
select aaa.period
,aaa."PayeeID"
,aaa."Reports_to" MANAGER
,aaa."Component" comp,
aaa."Current_YTD_Actual" cytd,
aaa."Current_YTD_Plan" cytp
from nbr_var_data aaa
where aaa."Comp_Plan_Name" not in ('MISC_COMP','GM_2017')
AND "Comp_Plan_Name" not in ('MISC_COMP')
AND "Comp_Plan_Name" not LIKE '%GM%'
and aaa.period = (select max(aaa.period) from Nbr_Var_Data)
))
)
where 1=1
group by period, rep_code, comp, bucket, manager )
group by period, rep_code, comp, manager )) group by period, manager, comp)
SELECT DISTINCT
dc.rep PID
,dc.period
,ee.PAYEE_NAM
,dc.comp
,Dc."GT99"
,Dc."90TO99"
,Dc."80TO89"
,Dc."70TO79"
,Dc."LT70"
,Dc."NA"
,Ee.Parent_Payee_Id REPORT_TO_PAYEE_ID
,Ee.Parent_Payee_Nam REPORT_TO_NAME
FROM (SELECT
--period ,
--empl_id ,
gg.payee_id ,
gg.payee_nam ,
--lvl ,
ff.parent_payee_id ,
ff.PARENT_PAYEE_NAM
--parent_lvl ,
--mnth_disp
FROM (SELECT DISTINCT
dd.period
,dd.PARENT_PAYEE_ID
,ee.PAYEE_NAM PARENT_PAYEE_NAM
from (
SELECT DISTINCT
PERIOD,
PARENT_PAYEE_ID
FROM FI_CHANNEL_HIER) dd
left join FI_CHANNEL_HIER ee
on dd.PARENT_PAYEE_ID = ee.PAYEE_ID
WHERE DD.PERIOD = (select max(DD.PERIOD) from FI_CHANNEL_HIER )) ff
LEFT JOIN FI_CHANNEL_HIER gg
ON ff.PARENT_PAYEE_ID = gg.PARENT_PAYEE_ID) ee,
NEW_REP_DATA dc
WHERE EE.PAYEE_ID = DC.Rep
AND dc.period = (select max(period) from NEW_REP_DATA)
;

How can i take highest date in same person

Hi I have two table like that:
First: Tcustcounselm
Second: Tcustcounseldt
Tcustcounseldt include these columns : Counsel_Seq, Proc_Note, Proc_Date
Tcustcounselm include these columns : Counsel_Seq, Cust_No, Proc_Date
I have customers and I want to retrieve the customer proc_note (refund detail). Some customers have more than one refund detail, I only want the latest one.
This is my plsql code but when I run it it gives the same cust_no twice when I only want to see the latest one.
Select
A.Cust_No,
Max(To_Char(B.Proc_Date, 'yyyy/mm/dd hh24:mi:ss')) As Proc,
B.Proc_Note,
A.Counsel_Seq
FROM Tcustcounselm A,
Tcustcounseldt B
WHERE
A.Counsel_Seq = B.Counsel_Seq
--AND B.Do_Flag ='40'
AND A.Proc_Date BETWEEN TO_DATE('2013/07/08', 'YYYY/MM/DD') AND TO_DATE('2013/07/08', 'YYYY/MM/DD')+1
GROUP BY
A.Cust_No,
B.Proc_Note,
A.Counsel_Seq
ORDER BY 2 DESC;
I thınk MAX is problem so i tried different sample code but same problem
SELECT A.Cust_No,
B.Proc_Note
FROM Tcustcounselm A ,
(SELECT Counsel_Seq,
Proc_Note,
Rank () Over (Partition By Counsel_Seq Order By Proc_Date Desc) As Priority
From Tcustcounseldt
) B
Where A.Counsel_Seq = B.Counsel_Seq
--And B.Priority = 1
AND A.Proc_Date BETWEEN TO_DATE('2013/07/08', 'YYYY/MM/DD') AND TO_DATE('2013/07/08', 'YYYY/MM/DD')+1;
This (or somehing similar) should work
SELECT A.Cust_No,
To_Char(B.Proc_Date, 'yyyy/mm/dd hh24:mi:ss') As Proc,
B.Proc_Note,
A.Counsel_Seq
FROM Tcustcounselm B
INNER JOIN Tcustcounseldt A
ON A.Counsel_Seq = B.Counsel_Seq
WHERE (A.Cust_No,B.Proc_Date) IN ( SELECT A.Cust_No,
max(B.Proc_Date) PD
FROM Tcustcounselm B
INNER JOIN Tcustcounseldt A
ON A.Counsel_Seq = B.Counsel_Seq
GROUP BY A.Cust_No)
I had time to play with sqlfiddle and I fixed the query, try to check it here.

Linq to entities query adding inner join instead of left join

I'd like to know why INNER JOINs are generated instead of LEFT and why the whole view is selected before join instead of just adding LEFT JOIN view.
I'm trying to post a table of information which is spread out over several tables. Basically I want to search by the date and return all the information for events happening today, yesterday, this month - whatever the user selects. The query is quite long. I added DefaultIfEmpty to all the tables except the main one in an attempt to get LEFT JOINs but it just made a mess.
using (TransitEntities t = new TransitEntities())
{
var charters = from c in t.tblCharters
join v in t.tblChartVehicles.DefaultIfEmpty()
on c.Veh
equals v.ChartVehID
join n in t.tblNACharters.DefaultIfEmpty()
on c.Dpt.Substring(c.Dpt.Length - 1)
equals SqlFunctions.StringConvert((double)n.NAID)
join r in t.tblChartReqs.DefaultIfEmpty()
on c.ChartReqID
equals r.ChartReqID
join f in t.tblCharterCustomers.DefaultIfEmpty()
on c.Dpt
equals (f.DptID == "NONAFF" ? SqlFunctions.StringConvert((double)f.CustID) : f.DptID)
join d in t.tblChartReqDocs.DefaultIfEmpty()
on c.Attach
equals SqlFunctions.StringConvert((double)d.DocID)
join s in t.tblChartSupAttaches.DefaultIfEmpty()
on c.SupAttach
equals SqlFunctions.StringConvert((double)s.DocID)
join p in (from e in t.v_EmpData select new {e.UIN, e.First, e.Last}).DefaultIfEmpty()
on c.TakenUIN
equals p.UIN
where c.BeginTime > EntityFunctions.AddYears(DateTime.Now,-1)
select new
{
ChartID = c.ChartID,
Status = c.Status,
...
Website = r.Website,
};
//select today's events
gvCharters.DataSource = charters.Where(row => (row.BeginTime.Value >= midnight && row.BeginTime.Value < midnight1));
This results in very convoluted SQL:
SELECT
[Extent1].[ChartID] AS [ChartID],
[Extent1].[Status] AS [Status],
...
[Join5].[Website] AS [Website],
FROM [dbo].[tblCharters] AS [Extent1]
INNER JOIN (SELECT [Extent2].[ChartVehID] AS [ChartVehID], [Extent2].[Descr] AS [Descr]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]
LEFT OUTER JOIN [dbo].[tblChartVehicles] AS [Extent2] ON 1 = 1 ) AS [Join1] ON ([Extent1].[Veh] = [Join1].[ChartVehID]) OR (([Extent1].[Veh] IS NULL) AND ([Join1].[ChartVehID] IS NULL))
INNER JOIN (SELECT [Extent3].[NAID] AS [NAID], [Extent3].[Descr] AS [Descr]
FROM ( SELECT 1 AS X ) AS [SingleRowTable2]
LEFT OUTER JOIN [dbo].[tblNACharter] AS [Extent3] ON 1 = 1 ) AS [Join3] ON ((SUBSTRING([Extent1].[Dpt], ((LEN([Extent1].[Dpt])) - 1) + 1, (LEN([Extent1].[Dpt])) - ((LEN([Extent1].[Dpt])) - 1))) = (STR( CAST( [Join3].[NAID] AS float)))) OR ((SUBSTRING([Extent1].[Dpt], ((LEN([Extent1].[Dpt])) - 1) + 1, (LEN([Extent1].[Dpt])) - ((LEN([Extent1].[Dpt])) - 1)) IS NULL) AND (STR( CAST( [Join3].[NAID] AS float)) IS NULL))
INNER JOIN (SELECT [Extent4].[ChartReqID] AS [ChartReqID], [Extent4].[Event] AS [Event], [Extent4].[ContactName] AS [ContactName], [Extent4].[ContactPhone] AS [ContactPhone], [Extent4].[Website] AS [Website]
FROM ( SELECT 1 AS X ) AS [SingleRowTable3]
LEFT OUTER JOIN [dbo].[tblChartReq] AS [Extent4] ON 1 = 1 ) AS [Join5] ON ([Extent1].[ChartReqID] = [Join5].[ChartReqID]) OR (([Extent1].[ChartReqID] IS NULL) AND ([Join5].[ChartReqID] IS NULL))
INNER JOIN (SELECT [Extent5].[CustID] AS [CustID], [Extent5].[Dpt] AS [Dpt], [Extent5].[DptID] AS [DptID]
FROM ( SELECT 1 AS X ) AS [SingleRowTable4]
LEFT OUTER JOIN [dbo].[tblCharterCustomers] AS [Extent5] ON 1 = 1 ) AS [Join7] ON ([Extent1].[Dpt] = (CASE WHEN (N'NONAFF' = [Join7].[DptID]) THEN STR( CAST( [Join7].[CustID] AS float)) ELSE [Join7].[DptID] END)) OR (([Extent1].[Dpt] IS NULL) AND (CASE WHEN (N'NONAFF' = [Join7].[DptID]) THEN STR( CAST( [Join7].[CustID] AS float)) ELSE [Join7].[DptID] END IS NULL))
INNER JOIN (SELECT [Extent6].[DocID] AS [DocID], [Extent6].[FileName] AS [FileName]
FROM ( SELECT 1 AS X ) AS [SingleRowTable5]
LEFT OUTER JOIN [dbo].[tblChartReqDocs] AS [Extent6] ON 1 = 1 ) AS [Join9] ON ([Extent1].[Attach] = (STR( CAST( [Join9].[DocID] AS float)))) OR (([Extent1].[Attach] IS NULL) AND (STR( CAST( [Join9].[DocID] AS float)) IS NULL))
INNER JOIN (SELECT [Extent7].[DocID] AS [DocID], [Extent7].[FileName] AS [FileName]
FROM ( SELECT 1 AS X ) AS [SingleRowTable6]
LEFT OUTER JOIN [dbo].[tblChartSupAttach] AS [Extent7] ON 1 = 1 ) AS [Join11] ON ([Extent1].[SupAttach] = (STR( CAST( [Join11].[DocID] AS float)))) OR (([Extent1].[SupAttach] IS NULL) AND (STR( CAST( [Join11].[DocID] AS float)) IS NULL))
INNER JOIN (SELECT [Extent8].[First] AS [First], [Extent8].[Last] AS [Last], [Extent8].[UIN] AS [UIN]
FROM ( SELECT 1 AS X ) AS [SingleRowTable7]
LEFT OUTER JOIN (SELECT
[v_EmpData].[First] AS [First],
[v_EmpData].[Last] AS [Last],
[v_EmpData].[Legal] AS [Legal],
[v_EmpData].[Name] AS [Name],
[v_EmpData].[Email] AS [Email],
[v_EmpData].[UIN] AS [UIN],
[v_EmpData].[UserNM] AS [UserNM],
[v_EmpData].[Worker] AS [Worker],
[v_EmpData].[SUPERVISORNUM] AS [SUPERVISORNUM],
[v_EmpData].[Supervisor] AS [Supervisor],
[v_EmpData].[EmpArea] AS [EmpArea],
[v_EmpData].[Title] AS [Title],
[v_EmpData].[FullName] AS [FullName],
[v_EmpData].[HireDate] AS [HireDate],
[v_EmpData].[WORKERTYPENM] AS [WORKERTYPENM],
[v_EmpData].[Birth] AS [Birth],
[v_EmpData].[HOMESTREET] AS [HOMESTREET],
[v_EmpData].[HOMECITY] AS [HOMECITY],
[v_EmpData].[HOMEZIP] AS [HOMEZIP],
[v_EmpData].[HOMESTATE] AS [HOMESTATE],
[v_EmpData].[PicID] AS [PicID],
[v_EmpData].[WorkPhone] AS [WorkPhone],
[v_EmpData].[HomePhone] AS [HomePhone],
[v_EmpData].[WorkCellPhone] AS [WorkCellPhone]
FROM [dbo].[v_EmpData] AS [v_EmpData]) AS [Extent8] ON 1 = 1 ) AS [Join13] ON ([Extent1].[TakenUIN] = [Join13].[UIN]) OR (([Extent1].[TakenUIN] IS NULL) AND ([Join13].[UIN] IS NULL))
WHERE ([Extent1].[BeginTime] > (DATEADD (year, -1, SysDateTime())))
AND ('C' <> [Extent1].[Status])
AND ([Extent1].[BeginTime] >= '11/28/2012 12:00:00 AM')
AND ([Extent1].[BeginTime] < '11/29/2012 12:00:00 AM')
This is what my original SQL query looked like and what I was hoping it would be closer to:
SELECT
ChartID,
c.Status,
...
r.Website As Website,
FROM tblChartersNew c
LEFT JOIN (SELECT [Dpt],[DptID] FROM [DRVRDiscipline].[dbo].[tblCharterCustomers] Where Valid=1 and DptID <> 'NONAFF' UNION SELECT Dpt, CONVERT(nvarchar,CustID) AS DptID FROM [DRVRDiscipline].[dbo].[tblCharterCustomers] Where Valid=1 and DptID = 'NONAFF') f
ON RTRIM(c.Dpt) = f.DptID LEFT JOIN [tskronos].WfcSuite.dbo.VP_ALLPERSONV42 p ON p.PersonNUM = c.TakenUIN
LEFT JOIN tblChartVehicles v ON v.ChartVehID = c.Veh
LEFT JOIN tblNACharter n ON CAST(n.NAID AS varchar) = RIGHT(c.Dpt, LEN(c.Dpt)-1)
LEFT JOIN tblChartReq r
ON r.ChartReqID = c.ChartReqID
WHERE CONVERT(datetime,CONVERT(char(10),c.BeginTime,101)) = (SELECT TOP 1 CONVERT(datetime,CONVERT(char(10),BeginTime,101)) from tblChartersNew WHERE CONVERT(datetime,CONVERT(char(10),BeginTime,101)) >= CONVERT(datetime,CONVERT(char(10),GETDATE(),101)) ORDER BY BeginTime)
AND NOT c.ChartReqID IS NULL
ORDER BY BeginTime, ISNULL(f.Dpt,c.Dpt)
I also add a Select New on the view to avoid selecting all of the columns when I only need three but it didn't seem to make a difference. Instead of adding LEFT JOIN v_EmpData it adds LEFT OUTER JOIN and then selects all of the columns in the view. It seems to be ignoring the Select New.
I'd really like to transition to using Linq to Entities for the majority of my queries because intellisense makes it so much easier to make sure it's right and to have variations of queries without having to have separate functions for each but maybe I need to stick with plain old SQL. I know just enough to make a big mess. Any suggestions?
For complex queries like what you need.
I would suggest looking into FunctionImport.
MSDN Function Import
This would save you the headache of creating a LINQ that would be 1:1 to your expected generated SQL.

Trying to pull a variable only on row with max(date) while summing a different variable on all rows

I need to pull a value from the row that has the maximum date, while also summing all the values of a different column.
What I mean is something like this:
select
a.account_number,
a.client,
a.referral_date,
sum(b.amount),
max(b.date),
case when b.date = max(b.date) then b.due end as due
from a join b on a.account_number = b.account_number
group by a.account_number, a.client, a.referral_date, sum(b.amount), max(b.date), case when b.date = max(b.date) then b.due end
I'm sorry if this doesn't make sense, but I'm trying to sum ALL of "amount" while only getting "due" from the row with the maximum "date".
So if I join them so it only pulls max(date) I won't be able to sum ALL of the amounts.
I've been searching forever for this, but frankly I don't even know what to type into a search engine for this question. Thank you in advance for your help! Let me know how I can further clarify!
Steven
Wouldn't this work:
select a.account_number
, a.client,
, a.referral_date
, sum(b.amount)
, case when b.date = max(b.date) then b.due end as due
from a join b
on a.account_number = b.account_number
group by a.account_number, a.client, a.referral_date
... and if you're using PL\SQL then untested but:
select account_number
, a.client
, a.referral_date
, sum(b.amount)
, max_date
from ( select a.account_number
, a.client,
, a.referral_date
, b.amount
, max(b.date) over ( partition by a.account_number, a.client, a.referral_date ) as max_date
from a join b
on a.account_number = b.account_number )
group by a.account_number, a.client, a.referral_date, max_date
Not sure I precisely understand your goal, but how about this:
SELECT account_number, client, referral_date, amount, due
FROM (SELECT a.account_number,a.client,a.referral_date, b.due, b.date TheDate
, SUM(b.amount) OVER (PARTITION BY b.account_number) amount
, MAX(b.date) OVER (PARTITION BY b.account_number) max_dt
FROM a JOIN b ON a.account_number = b.account_number)
WHERE TheDate = max_dt;

Resources