I am storing employee attendance on a table 'attendance' having the following structure:
EmpID, CDate
Attendance system insert this table everyday with employee-id of all employees present on that particular day.
I need to find out absent statement of a particular employee. I can do this easily by selecting all distinct date that are not in - dates where the employee is present.
Is there any way I can remove the not in operator on that sql statement. Please help
Here is the sql query for employee with EmpId 01:
select distinct CDate
from attendance
where CDate not in (
Select CDate from attendance where EmpID='01')
The problem isn't in the NOT IN clause, it is the subquery.
You want something more like:
SELECT DISTINCT a1.CDate, if (EmpID=NULL, false,true) as Present
FROM attendance as a1
LEFT JOIN attendance as a2 USING (CDate)
WHERE a2.EmpID='01'
This is a cartesian join which pulls all of the dates, then joins the employee attendance status on that. Should be significantly faster than your subquery.
Updated, with tested code:
SELECT DISTINCT a1.CDate, IF (a2.EmpID IS NULL, false,true) as Present
FROM attendance AS a1
LEFT JOIN attendance AS a2 ON (a1.CDate = a2.CDate AND a2.EmpID='01')
My bad on the previous answer. I should have put the subselection into the ON instead of an aggregate.
You could change your mechanism to store data for each employee, each day.
Yes, it'll add a lot of rows, but how can you be sure that you'll get all dates from logged data? what if theres nobody at work today? no one will have absense?
If you'd go with:
EmpID, CDate, Present
1, {date}, 0|1
then you'd have simpler and faster query traded for table size:
select CDate from attendance where EmpID = 1 and status = 0;
Related
I have a task to make a database only in MySQL. I made 11 tables and connected them via foreign keys. I tried to make a simple query in order to return name and lastname of the patient in his diagnose, but I always get only a header with the first and last name and analysis.
The patient's table has nameID, name, last name, ID serial number, date of birth and so on, but I wanted only name and last name for the test query.
The second table I joined is analysis, which has analysisID, patientID, doctorID, hospitalID, diagnosis and so on.
My query is like this:
SELECT pat.name, pat.lastname
FROM patient pat
JOIN analysis a ON pat.patientID = a.patientID
group by a.analysisID
order by pat.lastname
This query returns 0 rows. Please help, I am new at mySQL. I read a lot of tutorials, read posts here about this problem and I still didn't find a solution.
I assume that you want to eliminate any duplicate analysisID's for the same person with the use of group by. If so, you could use the following:
Select a.analysisID, pat.name, pat.lastname
from patient pat, analysis a
where pat.patientID = a.patientID
group by a.analysisID, pat.name, pat.lastname
What the above query will do is return only one record when the analysisID, name and lastname are all the same.
I have a access table that has quarterly pricing data starting from 20100131 and goes on as 20100430, 20100731.... 20170131, 20170430. For each pricing date, there are many loans. Some loans stay in the portfolio, some loans are removed and some added for each pricing period. I would like to find the list of loans that exist in all periods and see their price for each period. So i have the "Loan_Number" field and "Price_Date" field. I would like to find the Loan Numbers that exist in all price date points. I appreciate the help.
Thanks!
Would have been nice to see some effort from you but I was intrigued with the challenge so here is what I accomplished.
1 - Need a dataset of all possible combinations of loan numbers and date values. So if you have a LoanNumbers table and a Periods table, create a Cartesian query called AllPairs:
SELECT LoanNumbers.Loan_Number, Periods.Price_Date FROM LoanNumbers, Periods;
If you don't have those tables, generate datasets with queries, assuming the data table has at least one record for every loan number and at least one record for every period:
SELECT DISTINCT Table1.Price_Date FROM Table1;
SELECT DISTINCT Table1.Loan_Number FROM Table1;
2 - Join AllPairs to data table for a 'find unmatched' query called LoanNoPeriod:
SELECT AllPairs.Loan_Number, AllPairs.Price_Date, Table1.Loan_Number, Table1.Price_Date
FROM AllPairs LEFT JOIN Table1 ON (AllPairs.Price_Date = Table1.Price_Date) AND (AllPairs.Loan_Number = Table1.Loan_Number)
WHERE (((Table1.Price_Date) Is Null));
3 - Final query:
SELECT * FROM Table1 WHERE Loan_Number NOT IN (SELECT AllPairs.Loan_Number FROM LoanNoPeriod);
Be aware these type of queries can perform very slowly and with very large datasets might not be practical.
My end result is a report of multiple employees that includes days worked in a date range. In my report, I need to have all dates in the range showing on the report whether the employee worked it or not.
So I have a table with dates worked and hours for each empl. I also created a table with dates far into the future. I think I need a query that joins the two tables and puts all dates for the date range - that will be prompted. added to the table of employee time worked.
Does anyone have any ideas how to join these tables and get all dates for each employee in the two week range that will be prompted?
First table Dates has only 1 column with dates way into the future.
Second table has Empl Name, Date worked, and hours worked.
You will need to use a nested query (aka. sub query) to create all combinations of employees and calendar days then you can do a left to your second table (timesheet table).
select *
from (select distinct empl_name, cal_date from first_tbl, second_tbl
where cal_date between [start date] and [end date]) as nested
left join second_tbl
on nested.empl_name = table_2.empl_name
and nested.cal_date = table_2.work_date
How to get Number of Employees Joined or Resigned by Quarterly in SQL
I have a Table called Mst_Employee
fields are
Emp_No, Emp_JoiningDate, Emp_ResignedDate, Emp_Status
Edit: Every half a year, not quarterly.
The easiest way to do analysis like this would be to use the DATEPART function in T-SQL. Assuming all you want is to know a specific quantity for all quarters in all years on your table, an example code would be:
SELECT
DATEPART(YEAR,Emp_JoiningDate) as [Year],
DATEPART(QUARTER,Emp_JoiningDate) as [Quarter],
COUNT(1) as [Emp Count]
FROM Mst_Employee
GROUP BY DATEPART(YEAR,Emp_JoiningDate),DATEPART(QUARTER,Emp_JoiningDate)
ORDER BY 1,2
This will show all the numbers of employee's joined in the quarter. The query can easily be modified to also show resigned employee's in that quarter, or you could use a separate query to show this data.
Just an additional comment, as you're in the Employee Table, you don't need to directly state "Emp_" under all of your attributes.
Sorry for the mega title... I was trying to be descriptive enough. I've got a table that contains event attendance data that has some erroneous data in it. The table definition is kind of like this:
id (row id)
date
company_name
attendees
It ended up with some cases where for a given date, there are two entries matching a company_name and date but one has attendees=0 and the other has attendees>0. In those cases, I want to discard the ones where attendees=0.
I know you can't join on the same table while deleting, so please consider this query to be pseudocode that shows what I want to accomplish.
DELETE FROM attendance a WHERE a.attendees=0 AND a.date IN (SELECT b.date FROM attendance b WHERE b.attendees > 0 AND b.company_name = a.company_name);
I also tried to populate a temporary table with the ids of the rows I want to delete, but that query hangs because of the IN (SELECT ...) clause. My table has thousands of rows so that just maxes out the CPU and then times out.
This ugly thing should work (using alias permit to avoid the You can't specify target table for update in FROM clause error)
DELETE FROM attendance
WHERE (attendees, date, company_name)
IN (SELECT c.a, c.d, c.c
FROM
(SELECT MIN(attendees) a, date d, company_name c
FROM attendance
GROUP BY date, company_name
HAVING COUNT(*) > 1) as c);
SqlFiddle