I have a table called Leaves which has Employee ID, Leave Type and Date. For example, If an employee with ID = 1234 applies for a sick leave from 1-June-2014 to 5-June-2014, this will be stored in Leave tables day by day, means that the following records will be added:
1234 sick leave 1-June-2014
1234 sick leave 2-June-2014
1234 sick leave 3-June-2014
1234 sick leave 4-June-2014
1234 sick leave 5-June-2014
This is considered as one case. To clarify what I mean by the case: The total cases is how many leave request had been applied… for example:
What I need is to get the following information by SQL statement (I should determine a period: 1-January-2014 to 30-December-2014, for example):
Sick leave cases: 2
Escort leave cases: 2
Study leave cases: 1
I am using PostgreSQL 9.2.
This design is a bit strange, because of these daily rows, if the same person will have several escort leaves, then you have to figure out different cases.
For this certain case you can use something like this
SELECT COUNT(*), leavetype
FROM (
SELECT leavetype
FROM Leaves
GROUP BY employee_id, leavetype
)
GROUP BY leavetype;
My suggestion is to use case_start and case_end dates for one case row.
Perhaps you can try this:
select leave_type, count(*)
from (
select employee_id, leave_type
from leaves
where date between ...
group by employee_id, leave_type) t
group by leave_type;
select LeaveType, count(EmployeeID) as TotalCases from(
select EmployeeID, LeaveType, count(LeaveType) as count_LeaveType
from Leaves
where Date BETWEEN '2007-02-01' AND '2007-02-31';
group by EmployeeID, LeaveType) as A
group by LeaveType, A.EmployeeID
Please find the SQLFiddle below.
SQL FIDDLE
SELECT leave_type,COUNT(leave_type) FROM
(SELECT leave_type,count(leave_type)
FROM leaves
WHERE Date BETWEEN '2014-01-01' AND '2014-12-31'
GROUP BY leave_type,emp_id) t
GROUP BY leave_type
Hope this solves your issue.
I am no sure how this will be done in PostgreSQL but in MySQL it can be achieve by following command :
QUERY
SELECT Leave type, count(Leave type)
FROM Leave
WHERE (Date BETWEEN '2014-01-01' AND '2014-12-30' )
GROUP BY Leave type
Related
I have a table table1 where I want to do a case statement that selects an employee ID based on the most recent hire date. An employee can have 2 separate user ID's in the system, I wanted to grab the user ID that was most recent. I tried approaching this by joining the fica_nbr of the employee from another table (table2), that way if it shows up more than once, I know the employee has 2 different hire dates and I can go
SELECT
CASE
WHEN COUNT(table2.fica_nbr) > 1
THEN SELECT(table1.employeeID)
WHERE employeeID is MAX date /*->This is the line im having trouble on, how would I get the employee ID that is the most up to date using the where clause*/
Thank you
you need to do something like this
change colunms with your required colunms
SELECT report_id, computer_id, date_entered
FROM reports AS a
WHERE date_entered = (
SELECT MAX(date_entered)
FROM reports AS b
WHERE a.report_id = b.report_id
AND a.computer_id = b.computer_id
)
I have a table as shown in image. Here user 'A' has no outtime where Id=2. If I select UserId,Name,MIN(inTime) and MAX(outtime) from MyTable ,then i will get First InTime and Last OutTime . Instead of selecting like that, I want to set User 'A' last outtime as null. How is it possible?.
Thanks in Advance
I assume you are using SQL Server:
select *
from(select name, userid, dateatt
from table
group by name, userid, dateatt)t
cross apply(select top 1 intime from table
where userid=t.userid and dateatt=t.dateatt order by id)i
cross apply(select top 1 outtime from table
where userid=t.userid and dateatt=t.dateatt order by id desc)o
By default, MAX and MIN do not include NULL when evaluating data.
See the below query I have modified for you taken from article here.
We will use COALESCE to replace any NULL EndDate with a date that is in the future that will not be coming up in our data anywhere, December 31, 2099 seems like a reasonable date for this. Next we take the MAX of the dates, which if NULL will evaluate as 12/31/2099 and be greater than any other date in our table. Wrap that in a CASE statement to replace the date 12/31/2099 back to NULL and group our data by StoreID.
SELECT
Name,
CASE WHEN MAX(COALESCE(outtime, ’12/31/2099′)) = ’12/31/2099′ THEN NULL ELSE MAX(outtime) END AS outtime
FROM WorkSchedule
GROUP BY Name
I have 2 Tables in Ms Access
tbl_Master_Employess
tbl_Emp_Salary
I want to show all the employees in the employee table linked with employee salary table
to link both table the id is coluqEmpID in both table
In the second table, I have a date column. I need a query which should fetch records from both tables using a particular date
I tried the following query:
select coluqEID as EmployeeID , colEName as EmployeeName,"" as Type, "" as Amt
from tbl_Master_Employee
union Select b.coluqEID as EmployeeID, b.colEName as EmployeeName, colType as Type, colAmount as Amt
from tbl_Emp_Salary a, tbl_Master_Employee b
where a.coluqEID = b.coluqEID and a.colDate = #12/09/2013#
However, it shows duplicates.
Query4
EmployeeID EmployeeName Type Amt
1 LAKSHMANAN
1 LAKSHMANAN Advance 100
2 PONRAJ
2 PONRAJ Advance 200
3 VIJAYAN
4 THIRUPATHI
5 VIJAYAKUMAR
6 GOVINDAN
7 TAMILMANI
8 SELVAM
9 ANAMALAI
10 KUMARAN
How would I rewrite my query to avoid duplicates, or what would be a different way to not show duplicates?
The problem with your query is that you are using union when what you want is a join. The union is first going to list all employees with the first part:
select coluqEID as EmployeeID , colEName as EmployeeName,"" as Type, "" as Amt
from tbl_Master_Employee
and then adds to that list all employee records where they have a salary with a certain date.
Select b.coluqEID as EmployeeID, b.colEName as EmployeeName, colType as Type,
colAmount as Amt
from tbl_Emp_Salary a, tbl_Master_Employee b
where a.coluqEID = b.coluqEID and a.colDate = #12/09/2013#
Is your goal to get a list of all employees and only display salary information for those who have a certain date? Some sample data would be useful. Assuming the data here: SQL Fiddle this query should create what you want.
Select a.coluqEID as EmployeeID, colEName as EmployeeName,
b.colType as Type, b.colAmount as Amt
FROM tbl_Master_Employees as a
LEFT JOIN (select coluqEID, colType, colAmount FROM tbl_EMP_Salary
where colDate = '20130912') as b ON a.coluqEID = b.coluqEID;
The first step is to create a select that will get you just the salaries that you want by date. You can then perform a join on this as if you were performing a separate query. You use a LEFT JOIN because you want all of the records from one side, the employees, and only the records that match your criteria from the second side, your salaries.
I believe you will need a join, however as to your question on Unique names.
select **DISTINCT** coluqEID as EmployeeID
Adding the distinct operator would give only uniquely returned results.
I always seem to trip myself up during these types of SQL Statements. Here is what I'm attempting to accomplish.
My Example Table
Name Date Type
Bob 9/28/11 1
Bob 9/27/11 1
Bob 9/28/11 2
Debra 9/28/11 1
I'm trying to write a SQL Statement that would give me all the names, their total count occured, and then a Date Filter. I'll write a rought statement with completely wrong syntax, but I think it'll convey what I'm attempting to do...I think.
SELECT Name, Count(*) As Total
FROM Table
GROUP BY Name, Total
WHERE Date = Today (I'm aware you can't do a WHERE in a GROUP BY) AND Type = 1
Essentially, I would like to get back a set of data that would show the Name, how many instances of Type 1 for today.
I don't think I'm searching for the proper question to actually be able to effectively research this on my own as well, probably because I'm wording it improperly.
Any help would be appreciated!
Your WHERE was in the wrong place:
SELECT Name, Count(*) As Total
FROM Table
WHERE Date = Today AND Type = 1
GROUP BY Name
You just need to move your WHERE after your FROM.
SELECT Name, Count(*) As Total
FROM Table
WHERE [Date] = CAST(getdate() as Date) -- or 'Jan 1 1990'
AND [Type] = 1
GROUP BY Name
WHERE comes before GROUP
SELECT Name, Count(*) As Total
FROM Table
WHERE Date >= #Today --assuming your date passed in has no time
AND Date < DATEADD(d,1,#Today)
AND Type = 1
GROUP BY Name, Total
example you can run
SELECT LEFT(name,1) FROM sysobjects
WHERE name < 'p'
GROUP BY LEFT(name,1)
I have a table named 'Attendance' which is used to record student attendance time in courses. This table has 4 columns, say 'id', 'course_id', 'attendance_time', and 'student_name'. An example of few records in this table is:
23 100 1/1/2010 10:00:00 Tom
24 100 1/1/2010 10:20:00 Bob
25 187 1/2/2010 08:01:01 Lisa
.....
I want to create a summary of the latest attendance time for each course. I created a query below:
SELECT course_id, max(attendance_time) FROM attendance GROUP BY course_id
The result would be something like this
100 1/1/2010 10:20:00
187 1/2/2010 08:01:01
Now, all I want to do is add the 'id' column to the result above. How to do it?
I can't just change the command to something like this
SELECT id, course_id, max(attendance_time) FROM attendance GROUP BY id, course_id
because it would return all the records as if the aggregate function is not used. Please help me.
This is a typical 'greatest per group', 'greatest-n-per-group' or 'groupwise maximum' query that comes up on Stack Overflow almost every day. You can search Stack Overflow for these terms to find many different examples of how to solve this with different databases. One way to solve it is as follows:
SELECT
T2.course_id,
T2.attendance_time
T2.id
FROM (
SELECT
course_id,
MAX(attendance_time) AS attendance_time
FROM attendance
GROUP BY course_id
) T1
JOIN attendance T2
ON T1.course_id = T2.course_id
AND T1.attendance_time = T2.attendance_time
Note that this query can in theory return multiple rows per course_id if there are multiple rows with the same attendance_time. If that cannot happen then you don't need to worry about this issue. If this is a potential problem then you can solve this by adding an extra grouping on course_id, attendance_time and selecting the minimum or maximum id.
What do you need the additional column for? It already has a course ID, which identifies the data. A synthetic ID to the query would be useless because it does not refer to anything. If you want to get the max from the query results for a single course, then you can add a where condition like this:
SELECT course_id, max(attendance_time) FROM attendance GROUP BY course_id **WHERE course_id = your_id_here**;
If you mean that the column should be named 'id', you can alias it in the query:
SELECT course_id **AS id**, max(attendance_time) FROM attendance GROUP BY course_id;
You could make a view out of your query to easily access the aggregate data:
CREATE VIEW max_course_times AS SELECT course_id AS id, max(attendance_time) FROM attendance GROUP BY course_id;
SELECT * FROM max_course_times;
For SQL Server 2008 onwards, I like to use a Common Table Expression to add aggregated columns to queries:
WITH AttendanceTimes (course_id, maxTime)
AS
(
SELECT
course_id,
MAX(attendance_time)
FROM attendance
GROUP BY course_id
)
SELECT
a.course_id,
t.maxTime,
a.id
FROM attendance a
INNER JOIN AttendanceTimes t
ON a.course_id = t.course_id