a column may not be outer-joined to a subquery - mysql

get this error when i am using oracle, but it works fine in mysql
left outer join
daybreak.contract_details expiring on
expiring.acd_id =
(select
max(lastexpire.acd_id)
from
daybreak.contract_details lastexpire
where lastexpire.acd_aad_id =acc_aad_id and
lastexpire.acd_itemization_tcd_code in ('IIN_5') and
lastexpire.acd_expiry_dt between to_date('2014-01-01','yyyy-mm-dd')
and to_date('2014-02-01','yyyy-mm-dd') and
lastexpire.acd_term > 0
)
thanks

What exactly is your question?
You cannot specify a subquery in the join condition of an outer join in Oracle. Doing so will result in an ORA-1799 error.
It's almost always possible to rewrite such a query though. For example, you could:
left outer join ( SELECT acd_aad_id, max(acd_id) max_acd_id FROM daybreak.contract_details lastexpire WHERE
lastexpire.acd_itemization_tcd_code in ('IIN_5') and
lastexpire.acd_expiry_dt between to_date('2014-01-01','yyyy-mm-dd')
and to_date('2014-02-01','yyyy-mm-dd') and
lastexpire.acd_term > 0 ) max_ids ON max_ids.acd_aad_id = aac_aad_id
left outer join
daybreak.contract_details expiring on
expiring.acd_id = max_ids.acd_aad_id
... the idea being get the value of the subquery for every possible value in an inline view and then outer-join to that.
In Oracle 12c, you could use a LATERAL inline view for faster-performing variants of that approach.
An alternate approach would be to just outer join to all the values of daybreak.contract_details.acd_id, not just the max() value, and then filter out any values that aren't the maximum, later on in the query (keeping in mind that some of the values might be null (i.e., if there were no matches in contract_details at all).

Related

MAX(Date) is giving empty result

I have a table with exchange rate like below
And I am using the maxofdate to pick all these values based on currency code. But the query is giving blank.
Select USDAMOUNT * dbo.EXCHANGERATEAMT
from dbo.Amount_monthly
Left Join dbo.EXCHANGERATE on dbo.Amount_monthly.Currencycode=dbo.EXCHANGERATE.fromcurrencycode
WHERE ValidToDateTime = (Select MAX(ValidToDateTime) from dbo.EXCHANGERATE)
AND dbo.EXCHANGERATE.EXCHANGERATETYPECODE = 'DAY'
Using this statement
CONVERT(DATE,ValidToDateTime) = CONVERT(DATE,GETDATE()-1)
instead of subquery is giving me expected result.
Can someone correct this.
thanks in advance.
If I understand correctly, you need two things. First, the condition for the max() needs to match the condition in the outer query. Second, if you really want a left join, then conditions on the second table need to go in the on clause.
The resulting query looks like:
Select . . .
from dbo.Amount_monthly am Left Join
dbo.EXCHANGERATE er
on am.Currencycode = er.fromcurrencycode and
er.ValidToDateTime = (Select max(er2.ValidToDateTime)
from dbo.EXCHANGERATE er2
where er2.EXCHANGERATETYPECODE = 'DAY'
) and
er.EXCHANGERATETYPECODE = 'DAY';
I would write this using window functions, but that is a separate issue.
Try removing WHERE clause for ValidToDateTime and include it in the JOIN as AND condition
SELECT USDAMOUNT * dbo.EXCHANGERATEAMT
FROM dbo.Amount_monthly
LEFT JOIN dbo.EXCHANGERATE
ON dbo.Amount_monthly.Currencycode = dbo.EXCHANGERATE.fromcurrencycode
AND ValidToDateTime = (SELECT MAX(ValidToDateTime) --remove WHERE clause
FROM dbo.EXCHANGERATE)
AND dbo.EXCHANGERATE.EXCHANGERATETYPECODE = 'DAY';
I cleaned up your query a bit: as the other folks mentioned you needed to close the parentheses around the MAX(Date) sub-query, and if you reference a LEFT JOINed table in the WHERE clause, it behaves like an INNER JOIN, so I changed to in INNER. You also had "dbo" sprinkled in as a field prefix, but that (the namespace) only prefixes a database, not a field. I added the IS NOT NULL check just to avoid SQL giving the "null values were eliminated" SQL warning. I used the aliases "am" for the first table and "er" for the 2nd, which makes it more readable:
SELECT am.USDAMOUNT * er.EXCHANGERATEAMT
FROM dbo.Amount_monthly am
JOIN dbo.EXCHANGERATE er
ON am.Currencycode = er.fromcurrencycode
WHERE er.ValidToDateTime = (SELECT MAX(ValidToDateTime) FROM dbo.EXCHANGERATE WHERE ValidToDateTime IS NOT NULL)
AND er.EXCHANGERATETYPECODE = 'DAY'
If you're paranoid like I am, you might also want to make sure the exchange rate is not zero to avoid a divide-by-zero error.

SQL - OutterApply and Left Join

I'm working with a large stored procedure, I'm having trouble with a small portion of it.
When I execute a query on the table im joining, there can be 0, 1 or 2 results. If there are 0 results, I don't really care, my code returns null values, no big deal. If there is 1 result, my code returns the correct values, however, if there are 2 results, I am having trouble selecting the second result.
My code below works until the second OutterApply(the AHM2 stuff). Does anyone see what I am doing wrong?
The animal ID is identical for both OuterApplys. I just need to return the second result, if there is one, and if it is not the same as the first one.
SELECT TOP 1
AHM.AnimalHerdManagementId,
AHM.HerdManagementId,
AHM2.AnimalHerdManagementId,
AHM2.HerdManagementId,
HM.Code AS HerdManagementCode,
HM2.Code AS HerdManagementCode2
OUTER APPLY
(
SELECT TOP 1 AHM.AnimalHerdManagementId, AHM.HerdManagementId
FROM dbo.AnimalHerdManagement AHM
WHERE AHM.AnimalId = A.AnimalId AND ISNULL(AHM.EffectiveFrom, #EffectiveFrom) <= #EffectiveFrom
ORDER BY AHM.EffectiveFrom DESC
) AHM
LEFT JOIN dbo.HerdManagement HM ON AHM.HerdManagementId = HM.HerdManagementId
OUTER APPLY
(
SELECT TOP 1 AHM2.AnimalHerdManagementId, AHM2.HerdManagementId
FROM dbo.AnimalHerdManagement AHM2
WHERE AHM2.AnimalId = A.AnimalId AND AHM2.AnimalHerdManagementId != AHM.AnimalHerdManagementId AND ISNULL(AHM2.EffectiveFrom, #EffectiveFrom) <= #EffectiveFrom
ORDER BY AHM2.EffectiveFrom DESC
) AHM2
LEFT JOIN dbo.HerdManagement HM2 ON AHM2.HerdManagementId = HM2.HerdManagementId
I think I can help you with the OUTER APPLY but the method of getting the two different values is going to need some help as my solution is a total hack.
First, you don't need to join on the outer apply. The join is implied. So you can completely eliminate the join syntax from your query.
Second, AnimalHerdManagement looks/seems like a special table called a Junction Table. All the data contained in it is contained elsewhere (That it contains completely redundant data is why it's called a special table). But that is minor.
Finally, here is some example code I threw together that accomplishes what you are after. The method I am using to retrieve different results on the two outer apply's is a hack, but if you are sure that will always be true, it might work. I am not able to get a multi-level outer apply to work.
select * from AH_Animal A
outer apply
(
select max (HerdManagementID) as HerdMgmtID1 from AH_AnimalHerdManagement HM1 where HM1.AnimalID = A.AnimalID
) as z
outer apply
(
select min (HerdManagementID) as HerdMgmtID2 from AH_AnimalHerdManagement HM2 where HM2.AnimalID = A.AnimalID
) as zz
I hope that helped. There has to be another solution to this, as this would not work at all if you ever expected 3 results.
Query Results:

MySQL COUNT on WHERE Statement

Pleas help me on why COUNT condition on WHERE statement commits an error, and how could i fix it?.
SELECT jq.taskqueueid,jq.jobid
FROM (SELECT p.taskID `curentTaskID`,
p.taskName `currentTaskName`,
p.processingType `currentProcessingType`,
p1.taskID `prevTaskID`,
p1.taskName `prevTaskName`,
p1.processingType `prevProcessingType`
FROM projecttask p
LEFT JOIN projecttask p1
ON p.sequenceNo=p1.nextTaskSequence
AND p.projectID=p1.projectID
WHERE p.taskID=18) task
INNER JOIN taskslogs tl
ON tl.taskID=task.`prevTaskID`
AND tl.statusDefinitionID=1
INNER JOIN jobqueue jq
ON tl.taskqueueid=jq.taskqueueid
WHERE COUNT(jq.taskqueueid)=COUNT(tl.taskqueueid)
to use an aggregate function like COUNT() you need to do a grouping of data, if you want to use it as a condition you can't use WHERE for this, since WHERE conditions are considered before aggregation. Use GROUP BY with HAVING instead. (see also http://dev.mysql.com/doc/refman/5.0/en/select.html )

MYSQL get other table data in a join

I am currently running this SQL
SELECT jm_recipe.name, jm_recipe.slug
FROM jm_recipe
LEFT JOIN jm_category_recipe ON jm_category_recipe.recipe_id = jm_recipe.id
WHERE jm_category_recipe.category_id = $cat"
This returns the desired results except that I also need to return the name of the category that the recipe I am looking for is in, to do this I tried to add the field in to my SELECT statement and also add the table into the FROM clause,
SELECT jm_recipe.name, jm_recipe.slug, jm_category_name
FROM jm_recipe, jm_category
LEFT JOIN jm_category_recipe ON jm_category_recipe.recipe_id = jm_recipe.id
WHERE jm_category_recipe.category_id = $cat"
However this just returns no results, what am i doing wrong?
You need to join both tables:
SELECT jm_recipe.name, jm_recipe.slug, jm.category_name
FROM jm_recipe
INNER JOIN jm_category_recipe ON jm_category_recipe.recipe_id = jm_recipe.id
INNER JOIN jm_category ON jm_recipe.recipe_id = jm_category.recipe_id
WHERE jm_category_recipe.category_id = $cat
I've changed the joins to inner joins as well. You might want to make them both LEFT joins if you have NULLs and want them in the result.
Also, you're vulnerable to SQL Injection by simply copying over $cat.
Here's some PHP specific info for you (I'm assuming you're using PHP.)

Conditions on outer joins

I'm trying to come up with an Access query which is equivalent to this oracle query
select ledef_name,
count(class.EVT_PK) timesTaught
from ingenium.ledef course,
ingenium.evt class
where course.LEDEF_PK = class.EVT_LEDEFFK(+)
and class.EVT_STARTDT(+) > to_date('2009-01-01', 'yyyy-mm-dd')
group by ledef_name
In access I have
SELECT course.ledef_name, Count(class.EVT_PK) AS timesTaught
FROM INGENIUM_LEDEF AS course LEFT JOIN INGENIUM_EVT AS class ON course.LEDEF_PK = class.EVT_LEDEFFK
WHERE class.EVT_STARTDT>#1/1/2009#
GROUP BY course.ledef_name;
In the Oracle version I get rows with a 0 count but in Access those rows are missing. What is the access syntax to include rows where there is no match in class to a row in course?
I think that you may need to add another condition to your WHERE clause. Add an " OR Is Null" to the WHERE clause and try that?
SELECT course.ledef_name, Count(class.EVT_PK) AS timesTaught
FROM INGENIUM_LEDEF AS course LEFT JOIN INGENIUM_EVT AS class ON course.LEDEF_PK =
class.EVT_LEDEFFK
WHERE class.EVT_STARTDT>#1/1/2009# OR Is Null
GROUP BY course.ledef_name;
Are you by any chance using floating point values in the join columns (dates are floating points in Access)? Floating point comparisons do not always match exactly because of rounding and representation issues (even thought they print out as exactly the same date in queries).