How to get the recors with count zero if there are no records - sql

I have three tables like
I want to display the leave types with the count. For that I have written a query like
SELECT VM.vacation_id,
VM.vacation_desc,
isnull(sum(VR.total_hours_applied),0) AS totalCount
FROM EMPTYPE_VACATIONCONFIG VC
LEFT JOIN HR_Vacation_Master VM ON VC.VACATIONID=VM.vacation_id
INNER JOIN HR_Employee_Vacation_Request VR ON VR.vacation_id=VM.vacation_id
WHERE VR.employee_id=156
AND VC.BRANCHID=20
GROUP BY VM.vacation_desc,
VM.vacation_id
my query is working fine and giving results of existed vacationids only. like
I want third leave alos with zero total.
If the employee not applied any leave(in second table), that record not coming in list. I want that record also with the totalCount zero.
How can I do it

This is because of VR.employee_id=156 you are not allowing null row.
You can do that :
SELECT VM.vacation_id,
VM.vacation_desc,
isnull(sum(VR.total_hours_applied),0) AS totalCount
FROM EMPTYPE_VACATIONCONFIG VC
LEFT JOIN HR_Vacation_Master VM ON VC.VACATIONID=VM.vacation_id
LEFT JOIN HR_Employee_Vacation_Request VR
ON VR.vacation_id=VM.vacation_id AND VR.employee_id=156
WHERE VC.BRANCHID=20
GROUP BY VM.vacation_desc,
VM.vacation_id
Leave me a comment if this not works, I have some other ideas.

If one employee didn't apply any leave, there shouldn't have a record with his(or her) employee id in table HR_Employee_Vacation_Request , right? So I think you should use HR_Vacation_Master left outer join table HR_Employee_Vacation_Request .

Related

Record with latest date, where date comes from a joined table

I have tried every answer that I have found to finding the last record, and I have failed in getting a successful result. I currently have a query that lists active trailers. I am needing it to only show a single row for each trailer entry, where that row is based on a date in a joined table.
I have tables
trailer, company, equipment_group, movement, stop
In order to connect trailer to stop (which is where the date is), i have to join it to equipment group, which joins to movement, which then joins to stop.
I have tried using MAX and GROUP BY, and PARTITION BY, both of which error out.
I have tried many solutions here, as well as these
https://thoughtbot.com/blog/ordering-within-a-sql-group-by-clause
https://www.geeksengine.com/article/get-single-record-from-duplicates.html
It seems that all of these solutions have the date in the same table as the thing that they want to group by, which I do not.
SELECT
trailer.*
company.name,
equipment_group.currentmovement_id,
equipment_group.company_id,
movement.dest_stop_id, stop.location_id,
stop.*
FROM trailer
LEFT OUTER JOIN company ON (company.id = trailer.company_id)
LEFT OUTER JOIN equipment_group ON (equipment_group.id =
trailer.currenteqpgrpid)
LEFT OUTER JOIN movement ON (movement.id =
equipment_group.currentmovement_id)
LEFT OUTER JOIN stop ON (stop.id = movement.dest_stop_id)
WHERE trailer.is_active = 'A'
Using MAX and GROUP BY gives error "invalid in the select list... not contained in...aggregate function"
Welllllll, I never did end up figuring that out, but if I joined movements on to equipment group by two conditions, all is well. Each extra record was created by each company id.... company id is in EVERY table.

Select distinct record with join count records

I have two tables: Company and Contact, with a relationship of one-to-many.
I have another table Track which identifies some of the companies as parent companies to other companies.
I want to write a SQL query that selects the parent companies from Track and the amount of contacts that each parent has.
SELECT Track.ParentId, Count(Contact.companyId)
FROM Track
INNER JOIN Contact
ON Track.ParentId = Contact.companyId
GROUP BY Track.ParentId
however The result holds less records than when I run the following query:
SELECT DISTINCT Track.ParentId
FROM Track
I tried the first query with an added DISTINCT and it returned the same results (less then what it was meant to).
You're performing an INNER JOIN with the Contact table, which means that any rows from the first table (Track in this case) with no matches to the JOINed table will not show up in your results. Try using a LEFT OUTER JOIN instead.
The COUNT with Contact.companyId will only count rows where there is a match (Contact.companyId is not NULL). Since you're counting contacts that's fine as they will count as 0. If you were trying to count some other set of data and tried to do a COUNT on a specific column (rather than COUNT(*)) then any NULL values in that column would not count towards your total, which might or might not be what you want.
I used an INNER JOIN which returns only records that are identical in both tables.
To return all records from Track table, and records that match in the Contact table, I need to use LEFT JOIN.

SQL Server count() returns different results when using joins

I am new to SQL Server and I am not looking for a solution (but it may help others), rather, I would like to understand the behaviour / why I get two different results from the two pseudo queries below.
The reason I have joined two other tables is because I will need to count all items in Vehicle against the 'Date_Recorded' in 'Garage'. All recorded since 2010. So before I did this I wanted to be sure I was getting the same total count from the table 'Car' and also get the same result with the joins, before I added the 'isDate' on 'Garage' condition, that is when I noticed the difference in the results.
I would have thought the joins would have been ignored?
Hope someone can advise? Thanks in advance!
SELECT count(Car.CAR_ID) AS Car_ID
FROM Vehicle Car
INNER JOIN Road Rd
ON Car.CAR_ID = Rd.CAR_ID
JOIN Garage g
ON Rd.GARAGE_ID = g.GARAGE_ID
----------------------------------------------
Car_ID
----------------------------------------------
226923
SELECT count(Car.CAR_ID) AS Car_ID
FROM Vehicle Car
----------------------------------------------
Car_ID
----------------------------------------------
203417
INNER JOIN: Returns all rows when there is at least one match in BOTH tables.
LEFT JOIN: Return all rows from the left table, and the matched rows from the right table.
RIGHT JOIN: Return all rows from the right table, and the matched rows from the left table.
FULL JOIN: Return all rows when there is a match in ONE of the tables.
you are using inner join thats why you are getting the wrong result from the actual count() result.
if you want to get all the record from the left table the you have to use left join in this query then you'll get the result of count() same as the main table[left table].
You either have
multiple records in the Road table with the same Car_ID or
multiple records in the Road table with the same Garage_ID or
Both of the above
You may be able to run the following to get what you want (assuming there is always a match in the road and garage tables):
SELECT count(Distinct Car.CAR_ID) AS Car_ID
FROM Vehicle Car
INNER JOIN Road Rd
ON Car.CAR_ID = Rd.CAR_ID
JOIN Garage g
ON Rd.GARAGE_ID = g.GARAGE_ID

Multiple table join query, with count in Oracle SQL

I'm trying to count the number of inspections of each property in YR_Inspection table by counting the number of times the property number occurs in the table, i then need to display this next to the town the city the property is located in and the branch the property belongs to all in the same query. Here is the link to my ERD to try and give this question some context,
http://www.gliffy.com/pubdoc/4239520/L.png
this is the code so far, it works so far but as soon as i add YR_Branch.CITY i get,
ORA-00979: not a GROUP BY expression
SELECT YR_Property.PROPERTYNUM, COUNT(YR_Inspection.PROPERTYNUM) AS Number_of_inspections
FROM YR_Property
INNER JOIN YR_Inspection
ON YR_Property.PROPERTYNUM = YR_Inspection.PROPERTYNUM
JOIN YR_Branch
ON YR_Property.BRANCHNUM = YR_Branch.BRANCHNUM
GROUP BY YR_Property.PROPERTYNUM
To add the branch number and the city for the branch, add max values for each to the query - like so:
SELECT YR_Property.PROPERTYNUM,
COUNT(YR_Inspection.PROPERTYNUM) AS Number_of_inspections,
MAX(YR_Branch.BRANCHNUM) AS Branch_Number,
MAX(YR_Branch.CITY) AS Branch_City
FROM YR_Property
INNER JOIN YR_Inspection
ON YR_Property.PROPERTYNUM = YR_Inspection.PROPERTYNUM
JOIN YR_Branch
ON YR_Property.BRANCHNUM = YR_Branch.BRANCHNUM
GROUP BY YR_Property.PROPERTYNUM

Left Join with all rows from the left not matching the Where Clause

I have the following problem:
I have an account table and an entries for account table.
account_id
account_name
entry_id
account_idfk
entry_date
entry_amount
Now I want to query all entries for all accounts in a given period. Eg. I want all Entries for all accounts from October 2008 - October 2009. If there are no entries for this account at all, or there are only entries in other timeperiods for this account, I want the account returned as well.
My current query works, if there are no entries at all, or there are entries for this timeperiod for this account. However - it leaves out the Accounts which have only entries for other timeperiods.
SELECT * FROM Account a
LEFT JOIN Entries e ON e.account_idfk = a.account_id
WHERE e.entry_date BETWEEN '2009-08-13' AND '2009-08-13'
OR e.entry_date IS NULL
I know that the problem is in the where clause - I eliminate all Accounts for which only entries in other time periods exist.
But I have no idea how to restate the query to get the desired result...
Thanks,
Martin
Move that condition to the join:
SELECT
*
FROM
Account a
LEFT JOIN Entries e ON
e.account_idfk = a.account_id
AND e.entry_date BETWEEN '2009-08-13' AND '2009-08-13'
What you see here is the difference between a join and a where condition. The join will only join rows that meet that condition. However, with a left join, you still return all the rows in the left table. With the where clause, you're filtering rows after the join. In this case, you only want to join entries where the date is 8/13/09 (or 13/8/09, for those across the pond), but you want to return all accounts. Therefore, the condition needs to go into the join clause, and not the where.
This often gets confused with any outer join, because with an inner join, the result is the same no matter if the condition is in the join or where clause. However, this does not mean that they are equivalent, as demonstrated by you today!