How to show all employees absent dates only in MS Access 2010 query? - sql

I want to have a query which shows me records of only those employees that were absent on various dates.
I have two queries in MS Access 2010. One is qAllDatesAllEmp which has all monthly dates for all employees. Second is qDailyWorkEmp which shows date-wise the working of employees. Now, say Emp1 had only one missing date of 5-Jan-2019; emp2 had 15-Jan-2019 missing and so on, the result should show me only these missing dates with employee names. What i have tried so far is that I have joined the date field from qAllDatesAllEmp to the date field in qDailyWorkEmp with join arrow pointing from qAllDatesAllEmp to qDailyWorkEmp. I also added the date field from qDailyWorkEmp to the query grid below but removed the check mark. When I run this query, it gives blank result. I would really welcome the experts' help on how to get the desired output below.
My Sample Data:
Query1: qAllDatesAllEmp contains {WorkDate; empID; empName; CityBased}
Query2: qDailyWorkEmp contains {DailyDate; empID; empName; CityBased}
The SQL for this is as follows:
SELECT qDailyWorkEmp.empID, qDailyWorkEmp.empName, qDailyWorkEmp.CityBased
FROM qAllDatesAllEmp LEFT JOIN
qDailyWorkEmp
ON qAllDatesAllEmp.WorkDate = qDailyWorkEmp.DailyDate
WHERE (((qDailyWorkEmp.DailyDate) Is Null));
My desired output:
empID; EmpName; MissingDate
001; ABC; 5-Jan-2019
007; LMN; 15-Jan-2019
...and so on

From what I can gather from your question, it seems like you are on the right track with your left join query, however, since your qAllDatesAllEmp query contains the master data, you should output the data from this query for records for which the corresponding values are null in your qDailyWorkEmp query.
You also appear to have a typo in your query on this line:
qAllDatesAllEmp.WhatDate = qDailyWorkEmp.DailyDate
As you have stated in your question that the query qAllDatesAllEmp contains the fields:
Query1: qAllDatesAllEmp contains {WorkDate; empID; empName; CityBased}
WhatDate is not one of these fields.
You will also need to join the empID field in both queries, so that you are comparing the date field on a per-employee basis, as opposed to comparing each date with the dates for all employees - hence your join criteria should be:
qAllDatesAllEmp LEFT JOIN qDailyWorkEmp ON
qAllDatesAllEmp.WorkDate = qDailyWorkEmp.DailyDate AND
qAllDatesAllEmp.empID = qDailyWorkEmp.empID
With the information provided, I might suggest the following:
SELECT
qAllDatesAllEmp.empID,
qAllDatesAllEmp.empName,
qAllDatesAllEmp.CityBased
qAllDatesAllEmp.WorkDate as MissingDate
FROM
qAllDatesAllEmp LEFT JOIN qDailyWorkEmp ON
qAllDatesAllEmp.WorkDate = qDailyWorkEmp.DailyDate AND
qAllDatesAllEmp.empID = qDailyWorkEmp.empID
WHERE
qDailyWorkEmp.DailyDate IS NULL

Related

Connecting multiple queries and passing criteria from one query to another

I am trying to put together a query that will basically run another query on each return.
My current query puts together important info for each client, such as how long an average groom takes and the description of the type of haircut they get:
SELECT Query11.petId AS PetID,
Query11.petName AS PetName,
dbo_Customer.cstLName AS LastName,
Query11.lstValue AS Breed,
qryFindsPetAvgApptTime.TotalAppts,
dbo_vwPetGroom.pgrName AS GroomStyle,
dbo_ListValues.lstValue AS Haircut,
ROUND([AvgPTime]) AS AvgPrep,
ROUND([AvgBTime]) AS AvgBath,
ROUND([AvgDTime]) AS AvgDry,
ROUND([AvgGTime]) AS AvgGroom,
[AvgPrep] + [AvgBath] + [AvgDry] + [AvgGroom] AS AvgMinutes,
qryFindsPetAvgApptTime.AvgHours
FROM((Query11
LEFT JOIN qryFindsPetAvgApptTime ON Query11.petId = qryFindsPetAvgApptTime.PetID)
LEFT JOIN dbo_Customer ON Query11.petCustId = dbo_Customer.cstId)
LEFT JOIN (dbo_vwPetGroom
LEFT JOIN dbo_ListValues ON dbo_vwPetGroom.pgrLengthHairBodyLid = dbo_ListValues.lstId)
ON Query11.petId = dbo_vwPetGroom.pgrPetId;
I want to add in the average length between grooming appts to the above query info. Right now that is done in 2 seperate queries.
The first one pulls days between appts:
SELECT tblTimeLog.PetID,
tblTimeLog.PetName,
[ApptDate] - (SELECT MAX(T.ApptDate)
FROM tblTimeLog T
WHERE T.PetID = tblTimeLog.PetID
AND T.ApptDate < tblTimeLog.ApptDate) AS Diff,
tblTimeLog.ApptDate
FROM tblTimeLog
WHERE (((tblTimeLog.PetID) = [Enter PetID]))
ORDER BY tblTimeLog.ApptDate;
And then averaged out with this:
SELECT qryTimeLogDiffs.PetID,
qryTimeLogDiffs.PetName,
AVG(qryTimeLogDiffs.Diff) AS AvgOfDiff
FROM qryTimeLogDiffs
GROUP BY qryTimeLogDiffs.PetID,
qryTimeLogDiffs.PetName;
Is there a way to pass the PetID criteria from each return into the second query so it adds the average span between appts to the info in the first query??
Consider refactoring your second query to avoid the taxing correlated aggregate subquery. One approach involves first running an aggregate query based on a self join to return last appointment date for each PetID.
Even better, turn this query into an action query to populate a temporary table either with make-table query as shown below using INTO or regularly cleaning out a persistent table via delete and insert-select query:
SELECT curr.PetID,
curr.PetName,
curr.ApptDate,
MAX(prev.[AppDate]) AS MaxPrevDate
INTO lastApptTimeLog
FROM tblTimeLog AS curr
INNER JOIN tblTimeLog AS prev
ON curr.PetID = prev.PetID
WHERE prev.ApptDate < curr.AppDate
GROUP BY curr.PetID,
curr.PetName,
curr.ApptDate;
Then, base third aggregate query on this temp table and run the difference calculation. Finally, incorporate this query into first query.
SELECT PetID,
PetName,
AVG(ApptDate - MaxPrevDate) AS AvgOfDiff
FROM lastApptTimeLog
GROUP BY PetID,
PetName;

Expand Join to not limit data

I have a weird question - I understand that Joins return matching data based on the 'ON' stipulation, however the problem I am facing is I need the Business date back for both tables but at the same time i need to join on the date in order to get the totals correct
See below code:
Select
o.Resort,
o.Business_Date,
Occupied,
Comps,
House,
ADR,
Room_Revenue,
Occupied-(Comps+House) AS DandT,
Coalesce(gd.Projected_Occ1,0) AS Projected_Occ1,
Occupied-(Comps+House)+Coalesce(gd.Projected_Occ1,0) as Total
from Occupancy o
left join Group_Details_HF gd
on o.Business_Date = gd.Business_Date
and o.Resort = gd.resort
UNION ALL
select
o.Resort,
o.Business_Date,
Occupied,
Comps,
House,
ADR,
Room_Revenue,
Occupied-(Comps+House) AS DandT,
Coalesce(gd.Projected_Occ1,0) AS Projected_Occ1,
Coalesce(Occupied-(Comps+House),0)+Coalesce(gd.Projected_Occ1,0) as Total
from Occupancy_Forecast o
FULL OUTER JOIN Group_Details_HF gd
on o.Business_Date = gd.Business_Date
and o.Resort = gd.resort
Currently, this gives me the desired results from the Occupancy and Occupancy forecast table however when the business date does not exist in the occupancy forecast table it ignores the group_details table, I need the results to combine the dates when they exist in both or give the unique results for each when there is no match
I have decided to create another pivot table storing the details from Group_Details_HF and then Union together the two tables which has given me the desired result rather than fiddling with the join :)

Building a sql query from two tables

I created a query which selects sum of columns from a table grouped by a field in Crystal reports, now I want the result to be filtered by a date range from another table which I am unable to do. Please Help...
Here is the query
SELECT
BDETAIL.HSN,
SUM(BDETAIL.TAXABLE),
SUM(BDETAIL.SGST_V),
SUM(BDETAIL.CGST_V),
SUM(BDETAIL.TOTAL),
BDETAIL.SGST_P
FROM
BDETAIL
JOIN
BILL ON BDETAIL.BILL_ID = BILL.BILL_ID
WHERE
BILL.BDATE BETWEEN {?FROM_DATE} AND {?TO_DATE} )
GROUP BY
BDETAIL.HSN, BDETAIL.SGST_P
I finally figured it out ..here is the working query
SELECT BDETAIL.HSN,
sum(BDETAIL.TAXABLE),
Sum(BDETAIL.SGST_V),
Sum(BDETAIL.CGST_V),
Sum(BDETAIL.TOTAL),
BDETAIL.SGST_P
FROM BDETAIL INNER JOIN BILL ON
( BILL.BILL_ID = BDETAIL.BILL_ID AND
BILL.BDATE BETWEEN {?FROM_DATE} AND {?TO_DATE} )
GROUP BY BDETAIL.HSN, BDETAIL.SGST_P;
thank you all for showing interest in my issue.

Query that filters out results if they exist in a second table

I have two tables. First is a table Employees the second is TimeCard. I am trying to determine when employees are not here. Sample Tables:
So an employee name is returned if it meets the following criteria: Status = 1 and Date != '8/27/13'. However I only want an Employee returned once even if they have multiple entires in the TimeCard table as long as they are not on a specified date.
Try the following:
SELECT e.employee FROM employees e
WHERE status=1
AND NOT EXISTS ( SELECT 1 FROM timecard t
WHERE t.employee=e.employee
AND t.Date = '8/27/13')
where '8/27/13' will work only, if date is a varchar column. Otherwise you should use a more standard date format like '2013-8-27'.
Edit:
In MSSQL '8/27/13' will actually work, but it is still not a good idea to use this notation as it is not unambiguous when smaller numbers are used, like '5/6/7'. Depending on who entered it (and from which country they come), this could mean either May 6 2007, or 2005 May the 7th or 5 June 2007 ...
2. Edit:
Evidently not a good idea to prepare supper while you are putting together a SQLfiddle! The whole thing was buggy. I just fixed it and, of course corrected the typo with t.Date != '8/27/13' sorry for the confusion! See the corrected fiddle here: http://sqlfiddle.com/#!3/26454/1
Try this:
SELECT DISTINCT e.employee
FROM employees e
LEFT JOIN timecard t ON t.employee = e.employee
WHERE e.status = 1 AND (t.date != '8/27/13' OR t.date IS NULL)

How to view the Suggsetions sorted in the Database for the last three months?

I am a New ASP.NET Developer and I am trying to develop a simple suggestion box system. I have the following part of my database desing:
User Table: Username, Name, DivisionCode... etc
Division Table: SapCode, Division
SuggestionLog Table: ID, Title, Description, submittedDate, Username
(The first attribute is the primary key in each table and the attribute (submittedDate) is of DateTime data type)
Now, I need to develop a table that shows suggestions for the last three months. I already developed a query that shows the Employee Name, Username, Division, Suggestion Title, Suggestion Description. All what I want now is to show the Month. For example, to show the suggestions for the last three months, the Month column should show: Jan-2012, Dec-2011, Nov-2011 So how to do that?
My current SQL query:
SELECT dbo.SafetySuggestionsLog.Title, dbo.SafetySuggestionsLog.Description, dbo.SafetySuggestionsType.Type, dbo.SafetySuggestionsLog.Username,
dbo.employee.Name, dbo.Divisions.DivisionShortcut
FROM dbo.Divisions INNER JOIN
dbo.employee ON dbo.Divisions.SapCode = dbo.employee.DivisionCode INNER JOIN
dbo.SafetySuggestionsLog ON dbo.employee.Username = dbo.SafetySuggestionsLog.Username INNER JOIN
dbo.SafetySuggestionsType ON dbo.SafetySuggestionsLog.TypeID = dbo.SafetySuggestionsType.ID
The desired output is to display:
Employee Name, Username, Division, SuggestionTitle, SuggstionDescription, SuggestionType Month(submissionDate)
I reformatted you query so it would fit on the page without scrolling.
Hopefully this provides what you need. It uses DATENAME to get the month and year parts from the current date and DATEPART to do the "three months ago" calculation.
Note that DATEPART doesn't behave as you might expect - it counts the number of period-end boundaries (in this case months) - hence the condition is
...WHERE DATEDIFF(month,SafetySuggestionsLog.submittedDate,getdate()) < 3
because the last three months have two month-end boundaries between them.
I also added an ORDER BY clause.
SELECT dbo.SafetySuggestionsLog.Title,
dbo.SafetySuggestionsLog.Description,
dbo.SafetySuggestionsType.Type,
dbo.SafetySuggestionsLog.Username,
dbo.employee.Name,
dbo.Divisions.DivisionShortcut,
left(datename(month,SafetySuggestionsLog.submittedDate),3)
+ '-'
+ datename(year,SafetySuggestionsLog.submittedDate) AS SubmittedMonth
FROM dbo.Divisions
INNER JOIN dbo.employee
ON dbo.Divisions.SapCode = dbo.employee.DivisionCode
INNER JOIN dbo.SafetySuggestionsLog
ON dbo.employee.Username = dbo.SafetySuggestionsLog.Username
INNER JOIN dbo.SafetySuggestionsType
ON dbo.SafetySuggestionsLog.TypeID = dbo.SafetySuggestionsType.ID
WHERE DATEDIFF(month,SafetySuggestionsLog.submittedDate,getdate()) < 3
ORDER BY SafetySuggestionsLog.submittedDate DESC
It might also be worth noting that you don't have to fully qualify the name of all the columns in the query - it's valid SQL to alias the input tables like so:
...INNER JOIN dbo.SafetySuggestionsLog AS log
You can then refer to column names by alias in the query - e.g.
log.Username
instead of
dbo.SafetySuggestionsLog.Username
which makes it a bit easier to read.