Oracle Nested Select doesn't allow order by clause - sql

I have a requirement to fetch latest record from LEAD_REASSIGNMENT_TABLE LRD based on KSA.LEAD_ID = LRD.LEAD_ID.
Query is as follows ,
SELECT
KSA.LEAD_ID AS "leadId",
KSA.CREATED_ON AS "createdOn",
KSA.FIRST_NAME AS "firstName",
KSA.LAST_NAME AS "lastName",
KSA.CRN AS "crn" ,
KSA.MOBILE_NO AS "mobileNumber",
KSA.BRANCH_CODE AS "lpdBranchCode",
( SELECT T.DESCRIPTION FROM TERRITORY T WHERE T.ID IN
(
SELECT STM.TERRITORY_ID FROM SPOKE_TERRITORY_MAPPING STM
WHERE STM.SPOKE_CODE IN (SELECT SM.ID FROM SPOKE_MASTER SM WHERE SM.SPOKE_CODE=KSA.BRANCH_CODE AND SM.DELETE_FLAG='F') AND STM.DELETE_FLAG='F'
) AND T.DELETE_FLAG='F' AND ROWNUM<=1
) AS "lpdSubLocation" ,
(select lrd.LEAD_NEW_ASSIGNED_USER from LEAD_REASSIGNMENT_DETAILS lrd
where lrd.LEAD_ID = KSA.LEAD_ID and rownum <=1
) AS "NEW_ASSIGNED_USER"
FROM KSA_LEAD_DATA KSA
LEFT JOIN LEAD_PROSPECT_DETAILS LPD
ON KSA.LEAD_ID = LPD.KSA_LEAD_ID
LEFT JOIN ENTITY_TYPE_MAPPING ETM
ON LPD.LOAN_STATUS = ETM.ENTITY_CODE
WHERE KSA.DELETE_FLAG IS NOT NULL
ORDER BY KSA.LEAD_ID desc ;
Now when in the select i do
(select lrd.LEAD_NEW_ASSIGNED_USER from LEAD_REASSIGNMENT_DETAILS lrd
where lrd.LEAD_ID = KSA.LEAD_ID and rownum <=1
ORDER BY LRD.MODIFIED_ON) AS "NEW_ASSIGNED_USER"
I get ORA-00907: missing right parenthesis
00907. 00000 - "missing right parenthesis" Error
But when i use select without order by clause it works fine
(select lrd.LEAD_NEW_ASSIGNED_USER from LEAD_REASSIGNMENT_DETAILS lrd
where lrd.LEAD_ID = KSA.LEAD_ID and rownum <=1
) AS "NEW_ASSIGNED_USER"
If i use select without order by clause it wont guarantee me that i ll fetch the latest record from LEAD_REASSIGNMENT_TABLE.
NOTE
LEAD_REASSIGNMENT_TABLE contains 3-4 records with same lead_id
so i am selecting the latest record based on modified_on timestamp.
How should i use Order by clause inside nested select.?

I don't like correlated subqueries, not within the SELECT statement.
Anyway: if you rewrite that piece of code as below, I guess it should work.
(SELECT lrd.LEAD_NEW_ASSIGNED_USER
FROM LEAD_REASSIGNMENT_DETAILS lrd
WHERE lrd.LEAD_ID = KSA.LEAD_ID
AND lrd.modified_on = (SELECT MAX (lrd1.modified_on)
FROM LEAD_REASSIGNMENT_DETAILS lrd1
WHERE lrd1.lead_id = lrd.lead_id)) AS "NEW_ASSIGNED_USER"

Related

How could I join these queries together?

I have 2 queries. One includes a subquery and the other is a pretty basic query. I can't figure out how to combine them to return a table with name, workdate, minutes_inactive, and hoursworked.
I have the code below for what I have tried. The simple query is lines 1,2, and the last 5 lines. I also added a join clause (join punchclock p on p.servrepID = l.repid) to it.
Both these queries ran on their own so this is solely just the problem of combining them.
select
sr.sr_name as liaison, cast(date_created as date) workdate,
(count(date_created) * 4) as minutes_inactive,
(select
sr_name, cast(punchintime as date) as workdate,
round(sum(cast(datediff(minute,punchintime, punchouttime) as real) / 60), 2) as hoursworked,
count(*) as punches
from
(select
sr_name, punchintime = punchdatetime,
punchouttime = isnull((select top 1 pc2.punchdatetime
from punchclock pc2
where pc2.punchdatetime > pc.punchdatetime
and pc.servrepid = pc2.servrepid
and pc2.inout = 0
order by pc2.punchdatetime), getdate())
from
punchclock pc
join
servicereps sr on pc.servrepid = sr.servrepid
where
punchyear >= 2017 and pc.inout = 1
group by
sr_name, cast(punchintime as date)))
from
tbl_liga_popup_log l
join
servicereps sr on sr.servrepID = l.repid
join
punchclock p on p.servrepID = l.repid collate latin1_general_bin
group by
cast(l.date_created as date), sr.sr_name
I get this error:
Msg 102, Level 15, State 1, Line 19
Incorrect syntax near ')'
I keep getting this error but there are more errors if I adjust that part.
I don't know that we'll fix everything here, but there are a few issues with your query.
You have to alias your sub-query (technically a derived table, but whatever)
You have two froms in your outer query.
You have to join to the derived table.
Here's an crude example:
select
<some stuff>
from
(select col1 from table1) t1
inner join t2
on t1.col1 = t2.col2
The large error here is that you are placing queries in the select section (before the from). You can only do this if the query returns a single value. Else, you have to put your query in a parenthesis (you have done this) in the from section, give it an alias, and join it accordingly.
You also seem to be using group bys that are not needed anywhere. I can't see aggregation functions like sum().
My best bet is that you are looking for the following query:
select
sr_name as liaison
,cast(date_created as date) workdate
,count(distinct date_created) * 4 as minutes_inactive
,cast(punchintime as date) as workdate
,round(sum(cast(datediff(minute,punchintime,isnull(pc2_query.punchouttime,getdate())) as real) / 60), 2) as hoursworked
,count(*) as punches
from
punchclock pc
inner join servicereps sr on pc.servrepid = sr.servrepid
cross apply
(
select top 1 pc2.punchdatetime as punchouttime
from punchclock pc2
where pc2.punchdatetime > pc.punchdatetime
and pc.servrepid = pc2.servrepid
and pc2.inout = 0
order by pc2.punchdatetime
)q1
inner join tbl_liga_popup_log l on sr.servrepID = l.repid
where punchyear >= 2017 and pc.inout = 1

subquery from SELECT reference, gets me a "cannot be referenced from this part of the query"

I'm dealing with this question
I know the simple aggregate answer, but I figured out to try to challenge myself with subqueries.
SELECT outercm.surname, outercm.firstname, outercm.memid, subq.starttime
FROM cd.members outercm,
(
SELECT cm.memid, cb.starttime
from cd.members cm
JOIN cd.bookings cb ON cb.memid = cm.memid
WHERE cm.memid = outercm.memid
AND
DATE(starttime ) >= '01-09-2012'
ORDER BY cb.starttime
LIMIT 1
) as subq
And I get this error:
There is an entry for table "outercm", but it cannot be referenced
from this part of the query.
I've also tried subqueries from the FROM:
SELECT outercm.surname, outercm.firstname, outercm.memid,
(
SELECT cb.starttime
from cd.members cm
JOIN cd.bookings cb ON cb.memid = cm.memid
WHERE cm.memid = outercm.memid
AND
DATE(starttime ) >= '01-09-2012'
ORDER BY cb.starttime
LIMIT 1
)
FROM cd.members outercm
And i get this message:
java.lang.StringIndexOutOfBoundsException: String index out of range: -1
I'm not sure, when and how can i reference betweein inner and outer queries.
Thanks for the help
In Postgres, DISTINCT ON can be used to get results for highest/lowest row per group, in your example the "first booking". This is generally far efficient when compared to other options like GROUP BY + MIN() or using LIMIT in a correlated sub-query.
SELECT DISTINCT ON ( cm.memid ) cm.surname,
--get the first among memid
cm.firstname,
cm.memid,
cb.starttime
FROM cd.members cm
join cd.bookings cb
ON cb.memid = cm.memid
AND cb.starttime >= TIMESTAMP '2012-09-01'
ORDER BY cm.memid, --for each memid
cb.starttime; --that has the earliest date

Only month end values for each identifier

For the code below I am attempting to select only the month end values for all unique FundId's. The code below keeps giving me the error of
Msg 164, Level 15, State 1, Line 16
Each GROUP BY expression must contain at least one column that is not an outer reference.
How can I fix the where statement to pull all month end values for each fundid
SELECT TOP 10000 a.[PerformanceId]
,[InvestmentType]
,[EndDate]
,a.[CurrencyId]
,[AssetValue]
,c.FundId
FROM [StatusData_DMWkspaceDB].[dbo].[NetAssetsValidationFailure] a
LEFT JOIN MappingData_GAPortDB.dbo.PerformanceLevelMapping b
ON a.PerformanceId = b.PerformanceId
LEFT JOIN MappingData_GAPortDB.dbo.FundClassMatching c
ON b.SecId = c.SecId
WHERE a.EndDate IN (
SELECT MAX(a.EndDate)
From [StatusData_DMWkspaceDB].[dbo].[NetAssetsValidationFailure]
GROUP BY c.FundId, Month(a.EndDate), YEAR(a.EndDate))
This is your query:
SELECT TOP 10000 navf.[PerformanceId], [InvestmentType], [EndDate],
navf.[CurrencyId], [AssetValue], fcm.FundId
FROM [StatusData_DMWkspaceDB].[dbo].[NetAssetsValidationFailure] navf LEFT JOIN
MappingData_GAPortDB.dbo.PerformanceLevelMapping plm
ON navf.PerformanceId = plm.PerformanceId LEFT JOIN
MappingData_GAPortDB.dbo.FundClassMatching fcm
ON l.m.SecId = fcm.SecId
WHERE navf.EndDate IN (SELECT MAX(navf.EndDate)
From [StatusData_DMWkspaceDB].[dbo].[NetAssetsValidationFailure] navf
GROUP BY fcm.FundId, Month(navf.EndDate), YEAR(navf.EndDate)
);
Learn to use sensible table aliases, so the query is easier to write and to read.
In any case, your WHERE clause is only referencing outer tables in the GROUP BY. The message is quite clear.
I'm not even sure what you want to do, but I am guessing that this is a working version of what you want:
SELECT x.*
FROM (SELECT navf.[PerformanceId], [InvestmentType], [EndDate],
navf.[CurrencyId], [AssetValue], fcm.FundId,
ROW_NUMBER() OVER (PARTITION BY fcm.FundId, Month(navf.EndDate), YEAR(navf.EndDate)
ORDER BY navf.EndDate DESC
) as seqnum
FROM [StatusData_DMWkspaceDB].[dbo].[NetAssetsValidationFailure] navf LEFT JOIN
MappingData_GAPortDB.dbo.PerformanceLevelMapping plm
ON navf.PerformanceId = plm.PerformanceId LEFT JOIN
MappingData_GAPortDB.dbo.FundClassMatching fcm
ON l.m.SecId = fcm.SecId
) x
WHERE seqnum = 1;

ORA-00904: invalid identifier in subquery (in select clause)

I have a subquery that needs to use a value from the outer query. It fails because of the notorious "subquery in Oracle can't access a value from a parent query more than two level deeper" issue.
However, I can't figure out how to re-write it. Most examples on the web are for when the subquery is in the WHERE clause; mine is in the SELECT clause.
Help anyone?
select agre.*, agre.orga_ky,
orga.NAME_LA_LB as orga_name,
pers.LAST_NAME_LA_LB as SIGNATORY_ORGA__LASTNAME, pers.FIRST_NAME_LA_LB as SIGNATORY_ORGA_FIRSTNAME,
upper(pers.LAST_NAME_LA_LB) || ' ' || pers.FIRST_NAME_LA_LB as SIGNATORY_ORGA_FULLNAME,
-- Get the most current agreement for this orga and compare it with this row to find out if this row is current or expired
CASE WHEN (
SELECT AGRE_KY
FROM (
SELECT a.AGRE_KY
FROM T_AGREEMENT a
WHERE a.ORGA_KY = agre.orga_ky -- fail!!! ORA-00904: invalid identifier
ORDER BY a.REC_CREATION_DT DESC
)
WHERE ROWNUM = 1
) = agre.agre_ky THEN 'Current' ELSE 'Expired' END as agreement_status
from T_AGREEMENT agre
left outer join T_ORGANIZATION orga on agre.orga_ky = orga.orga_ky
left outer join T_PERSON pers on agre.SIGNATORY_ORGA_PERS_KY = pers.pers_ky
;
You can try using the row_number window function without the sub-query and check if it returns the expected result.
select agre.*, agre.orga_ky,
orga.NAME_LA_LB as orga_name,
pers.LAST_NAME_LA_LB as SIGNATORY_ORGA__LASTNAME, pers.FIRST_NAME_LA_LB as SIGNATORY_ORGA_FIRSTNAME,
upper(pers.LAST_NAME_LA_LB) || ' ' || pers.FIRST_NAME_LA_LB as SIGNATORY_ORGA_FULLNAME,
-- Get the most current agreement for this orga and compare it with this row to find out if this row is current or expired
CASE WHEN row_number() over(partition by agre.orga_ky order by agre.REC_CREATION_DT desc)
----------------^^^^^^^^^^^^ change the partitioning column per your requirement
= 1 THEN 'CURRENT'
ELSE 'EXPIRED' END as agreement_status
from T_AGREEMENT agre
left outer join T_ORGANIZATION orga on agre.orga_ky = orga.orga_ky
left outer join T_PERSON pers on agre.SIGNATORY_ORGA_PERS_KY = pers.pers_ky

how to get the latest price in sql query

I need get the price of lasted QuoteDate.
Right now i have query like these
SELECT dbo.INMT.Material, dbo.INMT.LastVendor, dbo.INMT.AvgCost, dbo.MSQD.Status, dbo.MSQH.QuoteDate, dbo.MSQD.UnitPrice
FROM dbo.INMT INNER JOIN
dbo.MSQD ON dbo.INMT.MatlGroup = dbo.MSQD.MatlGroup AND dbo.INMT.Material = dbo.MSQD.Material INNER JOIN
dbo.MSQH ON dbo.MSQD.MSCo = dbo.MSQH.MSCo AND dbo.MSQD.Quote = dbo.MSQH.Quote
GROUP BY dbo.INMT.Material, dbo.INMT.LastVendor, dbo.INMT.AvgCost, dbo.MSQD.Status, dbo.MSQD.UnitPrice, dbo.MSQH.QuoteDate
ORDER BY dbo.INMT.Material
and get the following result
and how can i run a query just get the highlighted record.i try to do something like where QuoteDate =max......but maybe my grouyping is not correct.
thanks
So, assuming SQL Server 2005+, you can use a CTE and ROW_NUMBER():
;WITH CTE AS
(
SELECT I.Material,
I.LastVendor,
I.AvgCost,
MD.Status,
MH.QuoteDate,
MD.UnitPrice,
RN = ROW_NUMBER() OVER( PARTITION BY I.Material, I.LastVendor,
I.AvgCost, MD.Status,
MD.UnitPrice
ORDER BY MH.QuoteDate DESC)
FROM dbo.INMT I
INNER JOIN dbo.MSQD MD
ON I.MatlGroup = MD.MatlGroup
AND I.Material = MD.Material
INNER JOIN dbo.MSQH MH
ON MD.MSCo = MH.MSCo
AND MD.Quote = MH.Quote
)
SELECT Material,
LastVendor,
AvgCost,
Status,
QuoteDate,
UnitPrice
FROM CTE
WHERE RN = 1
Use HAVING QuoteDate=max... after the order by clause.