left join excludes nulls and takes left value - sql

SELECT p.ticket AS posted,
e.ticket AS settled,
Sum(e.amount)
FROM post AS p
LEFT JOIN settle AS e
ON p.ticket = e.ticket
WHERE p.date = '2016-05-10 00:00:00.000'
GROUP BY p.pticket,
e.eticket
ORDER BY posted
I understand that the grouping or where is the culprit but I've tried so many variations, the rows for the two tables are :
(Table1=Table2)
(total = (item + tax= total))
So the second table has 2 rows that I sum. I need the date because it has to much info and I've tried "is null" in dates and in other places but can't get this right. Instead of null, it shows the value of the left table as if they match.

So I figured out! Just love this site and wanted to leave input for whoever runs into this, please correct me if my information is not accurate as I would like to explain in detail but basically, from what I understand and from SQL Fundamentals, nulls are considered outer rows and therefore I would need a "Left Outer Join":
SELECT p.ticket AS posted,
e.ticket AS settled,
Sum(e.amount)
FROM post AS p
LEFT JOIN settle AS e
ON p.ticket = e.ticket
WHERE p.date = '2016-05-10 00:00:00.000'
GROUP BY p.pticket,
e.eticket
ORDER BY posted
A good rule that stood out for me and helps me check my joins with nulls is that the Where clause should only have conditions to the table where the nulls will not be included, so you keep the outer rows, with the exception of "is null". You could use that with a column on the non-preserved table and still get nulls.

Related

Access SQL query without duplicate results

I made a query and wanted to not have any duplicates but i got some times 3 duplicates and when i used DISTINCT or DISTINCTROW i got only 2 duplicates.
SELECT f.flight_code,
f.status,
a.airport_name,
a1.airport_name,
f.departing_date+f.departing_time AS SupposedDepartingTime,
f.landing_date+f.landing_time AS SupposedLandingTime,
de.actual_takeoff_date+de.actual_takeoff_time AS ActualDepartingTime,
SupposedLandingTime+(ActualDepartingTime-SupposedDepartingTime) AS ActualLandingTime
FROM
(((Flights AS f
LEFT JOIN Aireports AS a
ON a.airport_code = f.depart_ap)
LEFT JOIN Aireports AS a1
ON f.target_ap = a1.airport_code)
LEFT JOIN Irregular_Events AS ie
ON f.flight_code = ie.flight_code)
LEFT JOIN Delay_Event AS de
ON ie.IE_code = de.delay_code;
had to use LEFT JOIN because when i used INNER JOIN i missed some of the things i wanted to show because i wanted to see all the flights and not only the flights that got delayed or canceled.
This is the results when i used INNER JOIN, you can see only the flights that have the status "ביטול" or "עיכוב" and that is not what i wanted.
[the results with LEFT JOIN][2]
[2]: https://i.stack.imgur.com/cgE2G.png
and when i used DISTINCT where you see the rows with the NUMBER 6 on the first column it appear only two times
IMPORTANT!
I just checked my query and all the tables i use there and i saw my problem but dont know how to fix it!
in the table Irregular_Events i have more the one event for flights 3,6 and 8 and that is why when i use LEFT JOIN i see more even thou i use distinct, please give me some help!
Not entirely sure without seeing the table structure, but this might work:
SELECT f.flight_code,
f.status,
a.airport_name,
a1.airport_name,
f.departing_date+f.departing_time AS SupposedDepartingTime,
f.landing_date+f.landing_time AS SupposedLandingTime,
de.actual_takeoff_date+de.actual_takeoff_time AS ActualDepartingTime,
SupposedLandingTime+(ActualDepartingTime-SupposedDepartingTime) AS ActualLandingTime
FROM
((Flights AS f
LEFT JOIN Aireports AS a
ON a.airport_code = f.depart_ap)
LEFT JOIN Aireports AS a1
ON f.target_ap = a1.airport_code)
LEFT JOIN
(
SELECT
ie.flight_code,
de1.actual_takeoff_date,
de1.actual_takeoff_time
FROM
Irregular_Events ie
INNER JOIN Event AS de1
ON ie.IE_code = de1.delay_code
) AS de
ON f.flight_code = de.flight_code
It is hard to tell what is the problem with your query without any sample of the output, and without any description of the structure of your tables.
But your problem is that your are querying from the flights table, which [I assume] can be linked to multiple irregular_events, which can possibly also be linked to multiple delay_event.
If you want to get only one row per flight, you need to make sure your joins return only one row too. Maybe you can do it by adding one more condition to the join, or by adding a condition in a sub-query.
EDIT
You could try to add a GROUP BY to the query:
GROUP BY
f.flight_code,
f.status,
a.airport_name,
a1.airport_name;

COUNT is outputting more than one row

I am having a problem with my SQL query using the count function.
When I don't have an inner join, it counts 55 rows. When I add the inner join into my query, it adds a lot to it. It suddenly became 102 rows.
Here is my SQL Query:
SELECT COUNT([fmsStage].[dbo].[File].[FILENUMBER])
FROM [fmsStage].[dbo].[File]
INNER JOIN [fmsStage].[dbo].[Container]
ON [fmsStage].[dbo].[File].[FILENUMBER] = [fmsStage].[dbo].[Container].[FILENUMBER]
WHERE [fmsStage].[dbo].[File].[RELATIONCODE] = 'SHIP02'
AND [fmsStage].[dbo].[Container].DELIVERYDATE BETWEEN '2016-10-06' AND '2016-10-08'
GROUP BY [fmsStage].[dbo].[File].[FILENUMBER]
Also, I have to do TOP 1 at the SELECT statement because it returns 51 rows with random numbers inside of them. (They are probably not random, but I can't figure out what they are.)
What do I have to do to make it just count the rows from [fmsStage].[dbo].[file].[FILENUMBER]?
First, your query would be much clearer like this:
SELECT COUNT(f.[FILENUMBER])
FROM [fmsStage].[dbo].[File] f INNER JOIN
[fmsStage].[dbo].[Container] c
ON v.[FILENUMBER] = c.[FILENUMBER]
WHERE f.[RELATIONCODE] = 'SHIP02' AND
c.DELIVERYDATE BETWEEN '2016-10-06' AND '2016-10-08';
No GROUP BY is necessary. Otherwise you'll just one row per file number, which doesn't seem as useful as the overall count.
Note: You might want COUNT(DISTINCT f.[FILENUMBER]). Your question doesn't provide enough information to make a judgement.
Just remove GROUP BY Clause
SELECT COUNT([fmsStage].[dbo].[File].[FILENUMBER])
FROM [fmsStage].[dbo].[File]
INNER JOIN [fmsStage].[dbo].[Container]
ON [fmsStage].[dbo].[File].[FILENUMBER] = [fmsStage].[dbo].[Container].[FILENUMBER]
WHERE [fmsStage].[dbo].[File].[RELATIONCODE] = 'SHIP02'
AND [fmsStage].[dbo].[Container].DELIVERYDATE BETWEEN '2016-10-06' AND '2016-10-08'

SQL LEFT JOIN WHERE not displaying right result

So I got this query:
Data structure:
Users
id---inlog----name----more stuff
llntoets
id---code----inlog----more stuff
oefeningen
id---speler---status----morestuff
(inlog and speler are always the same values for a user)
SELECT
// Some other stuff working
SUM(o.status) AS oefn
FROM users AS u
LEFT JOIN llntoets AS l
ON (u.inlog = l.inlog)
LEFT JOIN oefeningen AS o
ON (u.inlog = o.speler) AND o.status = 'afgewerkt'
WHERE
code = '$code'
GROUP BY l.inlog
ORDER BY klas ASC, klasnr ASC
Everything runs fine except 1 thing the oefn variable. It shows a number sometimes it shows the correct value and sometimes it shows a value that is much higher than it should be. Someone told me it could be because of the GROUP BY. Can someone help me pls?
It is supposed to count the total records from table oefeningen where status = 'afgewerkt' and where the speler is the inlog from users. Thanks, if you got other questions ask will try to explain more.
the SUM(o.status) in your query it is not supposed to count the total records of table oefeningen.
that sum is the sum of the values of all the joined rows that satisfy your criteria that can be a much higher number.
also note that applying the filter o.status = 'afgewerkt' you are performing a JOIN even if you wrote LEFT JOIN throghout the query.

applying DISTINCT SUM

I'm working on a code that would help me get the sum amount of GL Sub Heads (that's an accounting term) in a table. things is, there are multiple rows with the same GL Sub Head but with different amounts. I need to sum up the amounts of the table per GL Sub Head. that of course, involves the use of SUM and DISTINCT clauses. here's what I have so far:
select
gstt.bal_date,
sum(gstt.tot_dr_bal) as totalDr,
sum(gstt.tot_cr_bal) as totalCr
from(
select distinct
gam.gl_sub_head_code,
gstt.tot_dr_bal,
gstt.tot_cr_bal
from tbaadm.gam
left outer join tbaadm.eab
on gam.acid = eab.acid
and gam.bank_id = eab.bank_id
left outer join tbaadm.gstt
on gam.sol_id = gstt.sol_id
and gam.bank_id = gstt.bank_id
and gam.gl_sub_head_code = gstt.gl_sub_head_code
and gam.acct_crncy_code = gstt.crncy_code
where
gam.acct_ownership = 'O'
--and eab.eod_date = TO_DATE('3/24/2014', 'MM/DD/YYYY')
and gstt.bal_date = TO_DATE('3/24/2014', 'MM/DD/YYYY')
) group by gstt.bal_date, totalDr, totalCr
can't make the bloody thing work, though. I know I'm missing something, I just can't put my finger on what it is, and where should I put it in the code. Any help would be appreciated. If you need further clarifications, just ask.
EDIT
I've got the code to work now, somewhat. Because there's a problem.
select
bal_date,
gl_sub_head_code,
sum(tot_dr_bal),
sum(tot_cr_bal)
from(
select distinct
gam.gl_sub_head_code,
gstt.tot_dr_bal,
gstt.tot_cr_bal,
gstt.bal_date
from tbaadm.gam
left outer join tbaadm.eab
on gam.acid = eab.acid
and gam.bank_id = eab.bank_id
left outer join tbaadm.gstt
on gam.sol_id = gstt.sol_id
and gam.bank_id = gstt.bank_id
and gam.gl_sub_head_code = gstt.gl_sub_head_code
and gam.acct_crncy_code = gstt.crncy_code
where
gam.acct_ownership = 'O'
--and eab.eod_date = TO_DATE('3/24/2014', 'MM/DD/YYYY')
and gstt.bal_date = TO_DATE('3/24/2014', 'MM/DD/YYYY')
) group by bal_date, gl_sub_head_code
as you can see, there is a DISTINCT clause at the beginning of the subquery. whenever I remove that, TOAD outputs the same set of results. I get the same results regardless if I have the DISTINCT clause or not. I have a feeling there's something wrong with my code, as what I'm expecting is that the DISTINCT should make a difference.
"I get the same results regardless if I have the DISTINCT clause or not."
This means your query already returns a unique set of rows.
I have a feeling there's something wrong with my code, as what I'm expecting is that the DISTINCT should make a difference.
Why do you think that?
DISTINCT made a difference in your first query because you hadn't included bal_date in the sub-query's projection. So you have some gl_sub_head instances where the balances are the same for multiple days.
Except that you are filtering on bal_date so you should only get one value for it anyway. Hmmmm....
Clearly something is awry in your query. There are two obvious puzzlers.
Why do you have a LEFT OUTER JOIN with gstt? The hard filter on gstt.bal_date means you will only return records where gstt.bal_date is not null, so the result set would still be the same if that was an INNER JOIN.
Why bother querying eab at all? You don't use any values from it and the LEFT OUTER JOIN means it doesn't restrict the values retrieved from gam in anyway. Plus the fact that you have commented out the filter on eab.eod_date suggests that it currently produces a cross join which might generate multiple duplicate values which you then think you need a DISTINCT to eradicate.
So, I don't have an actual answer for you, but I think you need to re-visit your business logic and figure out what your query actually needs to do.

Join with time comparison

I have a trouble getting a code working with CI especially that I need to embed a complex condition on the join
I want to extract and count information from all fields in A even though not satisfying the condition which will result in zero 0 as count
First case that works great for count
$this->db->distinct();
$this->db->select('A.id, count(B.id) AS C');
$this->db->from('A');
$this->db->join('B','B.id=A.id','left outer');
$this->db->group_by('A.id');
Now if I want to add a condition on a row from A that is a datetime, so that we extract all information from A AFTER a given date, and same thing, if a condition is not satisfying we return 0 :
$this->db->distinct();
$this->db->select('A.id, count(B.id) AS C');
$this->db->from('A');
$this->db->join('B','B.id=A.id','left outer');
$this->db->where('B.date >',$date);
$this->db->group_by('A.id');
This code is working but retruning only rows satisfying the condition and not all the other rows with 0 as count.
Can someone tell me what is wrong with the where clause ?
Thanks
The where is undoing the left outer join. Can you do this?
$this->db->join('B','B.id=A.id and 'B.date >', $date, 'left outer');
In SQL, you would handle this by putting both conditions in the on statement:
from A left outer join
B
on B.id = A.id and B.date > $date;