Conditions on outer joins - ms-access

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).

Related

How to return row with diffrent value if "where" has not been met in MySQL

I have problem with receiving rows if id from one table dont match second one.
If zamowienia.id_telefon is null or dont match i dont recive whole row.
I want to instead get column crm2018.telefon.numer with "0" or null value. Please help :)
I tried something like that but its obvious syntax eror:
SELECT
crm2018.zamowienia.*,
crm2018.telefon.numer
FROM
crm2018.zamowienia
JOIN crm2018.telefon
WHERE
if (zamowienia.id_telfon != "0") zamowienia.id_telefon = telefon.id_telefon else crm2018.telefon.numer as "0"
Here's working code but with missing rows.
SELECT
crm2018.zamowienia.*,
crm2018.telefon.numer
FROM
crm2018.zamowienia
JOIN crm2018.telefon
WHERE
zamowienia.id_telefon = telefon.id_telefon
Just use LEFT JOIN instead of (INNER) JOIN.
Accordingly, you need to move the join condition from the WHERE clause to the ON clause of the join, to avoid filtering out unmatched records. Please note that as it is, your query has a JOIN without ON clause : this is a syntax error in all SQL dialects.
Finally, I would recommend using table aliases in the query : this makes it easier to read and to maintain.
SELECT
z.*,
t.numer
FROM
crm2018.zamowienia AS z
LEFT JOIN crm2018.telefon AS t
ON z.id_telefon = t.id_telefon
When no record is available in crm2018.telefon for the given crm2018.zamowienia, the record will still be displayed, with all columns coming from crm2018.telefon showing NULL values.
If needed, you can turn NULL values to 0 with the COALESCE() function, like :
COALESCE(t.numer, 0)

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.

How to sum all elements in an indexed table

I tried to make a query to my database with this structure: Data Base Structure
I did this query:
SELECT partido.acronimoPartido, SUM(votosacta.numVotos) FROM partido, votosacta WHERE votosacta.partido_idpartido=1 AND partido.idpartido=1
This query does work like I want but displays only the SUM of 'votos' for idpartido=1
I want to be able to sum numVotos from 'votosacta' table for each member of my 'partido' table indexed in 'votosacta' but I seem to not be able to get the right sintax.
I tried something like this:
SELECT partido.acronimoPartido, SUM(votosacta.numVotos) FROM partido, votosacta WHERE votosacta.partido_idpartido = partido.idpartido
You need a group by clause:
select p.acronimoPartido,
SUM(v.numVotos)
from partido p
join votosacta v on v.partido_idpartido = p.idpartido
group by p.acronimoPartido
Also, use explicit join syntax instead of old comma based syntax and use aliases to make your queries concise and readable.

a column may not be outer-joined to a subquery

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).

sql left join for two tables using a CONCAT string as the argument

I need to get a title from table 2, table 2 has title and id column.
Table 1 has some data and three of these columns concatenated together makeup the id that can be found in table 1.
I used CONCAT_WS() function and gave this column an alias name and need to use the Alias for the on argument(At least this is what I understood I needed to do)
I thought this could be a simple left join, yet it is not working for me.
This is my query
SELECT
table_openers.mail,
table_openers.f_name,
table_openers.l_name,
table_openers.Quality,
CONCAT_WS('-',
table_openers.esp,
table_openers.acc,
table_openers.group) as 't1aid',
table_groups.aid,
table_groups.group_name
FROM
lance_mailstats.table_openers
LEFT JOIN
lance_mailstats.table_groups ON table_groups.aid = t1aid;
I get results for mail, f_name, l_name, Quality and t1aid, but the aid and group_name columns of the second table return null.
I feel like you can't use an alias in the ON clause.
Try doing
LEFT JOIN
lance_mailstats.table_groups ON table_groups.aid = CONCAT_WS('-',
table_openers.esp,
table_openers.acc,
table_openers.group);
"You can use the alias in GROUP BY, ORDER BY, or HAVING clauses to refer to the column" (from dev.mysql.com/doc/refman/5.0/en/problems-with-alias.html).
And "The conditional_expr used with ON is any conditional expression of the form that can be used in a WHERE clause" (from dev.mysql.com/doc/refman/5.1/en/join.html).
So as a logical inference you're not allowed to use aliases in ON clauses.
try to use a subquery..
it goes like this.........
ex.
SELECT
tbl1.mail, tbl1.f_name, tbl1.l_name,tbl1.Quality, tbl1.t1aid,table_groups.aid,
table_groups.group_name
FROM
(SELECT
table_openers.mail,
table_openers.f_name,
table_openers.l_name,
table_openers.Quality,
CONCAT_WS('-',
table_openers.esp,
table_openers.acc,
table_openers.group) as 't1aid',
FROM
lance_mailstats.table_openers )tbl1
LEFT JOIN
lance_mailstats.table_groups ON table_groups.aid = tbl1.t1aid;