selecting point in time when change was made - sql

Say i have the following table:
id Name Status Date
1 John Working 11/11/2003
2 John Working 03/03/2004
3 John Quit 04/04/2004
4 John Quit 04/05/2004
5 John Quit 04/06/2004
6 Joey Working 03/05/2009
7 Joey Working 02/06/2009
8 Joey Quit 02/07/2009
9 Joey Quit 02/08/2009
10 Joey Quit 02/09/2009
I want to get the date when the change between working and quit occured, so that i get:
3 John Quit 04/04/2004
8 Joey Quit 02/07/2009
How would i do that?

select ID, Name, Status, Date
from tableName
where ID in (
select min(ID)
from tableName
where Status = 'Quit'
)
This will get the first record that has the status of 'Quit' for each person. It is not necessarily the chronologically first record though. If that is what you're are looking for let me know. Also, if so, can you be sure there won't be any duplicated names; this could be problematic if there are two different John's or Joey's.

select id, name, date
from tableName WHERE date =
(select MIN(date)
FROM tableName
WHERE NAME='<name>' AND date >= (select MAX(date)
FROM tableName WHERE NAME='<name>' AND status = 'Working')
)
Hopefully I didn't screw things up badly in the nested query there. This would only give you 1 user, you could wrap it in a function and call it passing the username or do something like make a temp table with distinct name inserted into it and loop through those names.
A lot of options exist for bringing it form just one user to all users.

Related

How do I display a guest's full name (family_name, given_name) from another table using only guest_id from the first table?

For my question I am to create a query showing the guest's full name that have made more than 2 bookings. It is to show the (family_name, given_name) in one column under the alias "Guest" AND alias "Count(*)" which what assume, counts the the guest_id from a2_booking (table1) which must be more than 2. The second table, "a2_guest", contains the guest_id (same as in a2_booking), family_name, given_name. What can I do to get the following query:
Guest COUNT(*)
-- ------------------------------------------------------------------------------------ ----------
-- Fellows, John 3
-- Gaye, Anthony 3
-- Grace, Thomas 3
-- Marvin, Leon 4
-- Oslovski, Boris 3
-- Rivers, Jill 3
-- Slater, Martin 3
-- Strettle, George
I only managed to use CONCAT to combine the family_name and given_name to one column on the first try and then I tried to count the guests that had multiple bookings made (but I didn't do the calculation greater than 2 yet).
Apologies all. I managed to find an answer that really helped.
SELECT x.family_name || ', ' || x.given_name AS "Guest", COUNT(y.guest) as
"COUNT(*)"
FROM a2_guest x JOIN a2_booking y
ON (x.guest_id = y.guest)
GROUP BY x.family_name || ', ' || x.given_name
HAVING COUNT(y.guest) > 2;
I appreciate the help though ;)

Get the row with the max date value with criteria - access 2007/2010

My main table, from which I take all the data from is "RequestTable" (I reduced it down to make it easier) in which I have:
ID_student
ID_professor
Date (and the three altogether are primary keys)
changeprofessor-note - if student wants to change the professor
then he/she should write in that field a sentence
why he/she wants to do the change
professor-reject-note - if the professor is not happy about the work of
the student, then he can choose not to mentor that
student anymore, leaving him without a mentor and the
student should choose another mentor later.
ID-seminar- after choosing a mentor the students
can choose the seminar they want to work on
changeofSeminar-note - if the student wants to change the seminar
then they need to write the reason why in here
(then the ID of the new seminar should be written in
the ID seminar field also)
IDapprove-reject - all approving or rejecting is going through this field
My initial theory was that the students could choose the mentor and the seminar in one row, but it seems too complicated now because I have no idea how to make everything work after changing mentors, declined mentoring, changing seminars and so on.
I set a more comfortable theory that all the students need to choose the mentor first. So that I could get easier the data of mentoring when needed. And I set "is null" in the query under the "ID_seminar" and "changeofseminar-note" because any changes on just the seminar part can't affect the rows where the students chosen their mentors/professors and got approved.
I implemented your code and got this:
SELECT [requesttable].ID_Student, Max([requesttable].Datum) AS MaxOfDatum, First([requesttable].ID_Profesor) AS ID_Profesor, [requesttable].ID_status_odobrenja
FROM [requesttable]
WHERE ((([requesttable].ID_Student) Not In (SELECT [ID_Student]
FROM [requesttable]
WHERE [IDapprove-reject] IS NOT NULL )))
GROUP BY [requesttable].ID_Student, [requesttable].IDapprove-reject, [requesttable].changeseminar-note, [requesttable].ID_seminar
HAVING ((([requesttable].IDapprovereject)=1) AND (([requesttable].changeseminar-note) Is Null) AND (([requesttable].Id_seminar) Is Null))
ORDER BY [requesttable].ID_Student, Max([requesttable].Datum), First([requesttable].ID_Profesor), [requesttable].IDapproved-reject;
And i get:
3 12 1
15 11 1
55 5 1
And I need:
3 6 1
15 6 1
52 5 1 - after being rejected by mentor 10,
the student choose another mentor (id 5) and got approved.
55 5 1
Old info below:
I got my query to this point and two other data are set to show only rows with null values to get this:
ID student Id professor date professor-reject-note ID accept/reject
3 12 12.11.2012 null 1
3 6 13.11.2012 null 1
52 10 12.11.2012 null 1
52 10 15.11.2012 NOT null 1
55 5 12.11.2012 null 1
I want my results to be
3 6 12.10.2013 null 1
15 6 7.1.2013 null 1
55 5 12.11.2012 null 1
Totally exclude StudentID 52 because of the professor-reject-note meaning the professor doesn't want to mentor the student anymore. Also I have a doubt about the ID accept/reject number in that option , maybe I could set it to 2 instead of 1 to make it easier. 1 means accepted, 2 would mean rejected, but if I set it to 2 and exclude the entire row I still can't get rid of the other ID 52 row. I'm a bit confused about it and have no clue how make it work.
If I set date to maxdate and Id professor to group by FIRST I almost get what I want, all the data is right except the Student ID 52 is still there - both rows.
You could use:
SELECT t.[id student],
t.[id professor],
t.DATE,
t.[professor-reject-note],
t.[id accept/reject]
FROM atable t
WHERE t.[id student] NOT IN
(SELECT [id student]
FROM atable
WHERE [professor-reject-note] IS NOT NULL)
Your field / column names could do with some work.

Select unique records and display as category headers in rails

I have a rails 3.2 app running on PostgreSQL, and have some data I want to display in my view, which is stored in the database in this structure:
+----+--------+------------------+--------------------+
| id | name | sched_start_date | task |
+----+--------+------------------+--------------------+
| 1 | "Ben" | 2013-03-01 | "Check for debris" |
+----+--------+------------------+--------------------+
| 2 | "Toby" | 2013-03-02 | "Carry out Y1.1" |
+----+--------+------------------+--------------------+
| 3 | "Toby" | 2013-03-03 | "Check oil seals" |
+----+--------+------------------+--------------------+
I would like to display a list of tasks for each name, and for the names to be ordered ASC by the first sched_start_date they have, which should look like ...
Ben
2013-03-01 – Check for debris
Toby
2013-03-02 – Carry out Y1.1
2013-03-03 – Check oil seals
The approach I starting taking was to run a query for unique names and order them by sched_start_date ASC, then run a query for each name to get their tasks.
To get a list of unique names, the SQL would look like this.
select *
from (
select distinct on (name) name, sched_start_date
from tasks
) p
order by sched_start_date;
I would like to know if this is the correct approach (querying for unique names then running another query for all their tasks), or if there is a better rails way.
To get the data sorted like you describe, you might want to use min() as window function in the ORDER BY clause:
SELECT name, sched_start_date, task
FROM tasks
ORDER BY min(sched_start_date) OVER (PARTITION BY name), 1, 2, 3
Your original query would need an additional ORDER BY item to get the earliest date per name:
SELECT DISTINCT ON (name) name, sched_start_date, task
FROM tasks
ORDER BY 1, 2, 3;
I also added task (3) as last ORDER BY item to break ties, in case there can be more than one per date.
But the output is still ordered by name, not by date.
Getting your peculiar format with all data stuffed into one column is a bit more complex:
SELECT one_col
FROM (
WITH x AS (
SELECT name, min(sched_start_date) AS min_start
FROM tasks
GROUP BY 1
)
SELECT 2 AS rnk, name
,sched_start_date::text || ' – ' || task AS one_col
,sched_start_date, min_start
FROM tasks
JOIN x USING (name)
UNION ALL
SELECT 1 AS rnk, name, name, NULL::date, min_start
FROM x
ORDER BY min_start, name, rnk, sched_start_date, task
) y
Assuming that you have associations in your model you would be able to run
#employees = Employee.order(:name, :sched_start_date, :task).includes(:tasks)
You could then iterate over them:
#employees.each do |employee|
employee.name
employee.tasks.each do |task|
task.name
end
end
This isn't gonna exactly match your needs, but should show you where to start.

how to get this result

I have a dropdown on page when user selects any value from it ; i am passing that value and filtering the result.
suppose if user select any bike from dropdown then from user table only those record should come which have that
bike and also those records should come where user have not any bike .
username vehicleID
========= =======
john 1
peter 1
maria 2
raso
pritam 4
if user selects vehicleID 2 then raso should also come along with maria.
I do not want to use UNION for this .
IF user does not select any thing all data should come by default on page
any other idea. thanks in advance
Use the following query, where the #VehicleID is the SelectedValue of the dropdownlist.
SELECT Username
FROM Table
WHERE #VehicleID IS NULL
OR VehicleID=#VehicleID
OR VehicleID IS NULL

SQL: How to select rows from a table while ignoring the duplicate field values?

How to select rows from a table while ignoring the duplicate field values?
Here is an example:
id user_id message
1 Adam "Adam is here."
2 Peter "Hi there this is Peter."
3 Peter "I am getting sick."
4 Josh "Oh, snap. I'm on a boat!"
5 Tom "This show is great."
6 Laura "Textmate rocks."
What i want to achive is to select the recently active users from my db. Let's say i want to select the 5 recently active users. The problem is, that the following script selects Peter twice.
mysql_query("SELECT * FROM messages ORDER BY id DESC LIMIT 5 ");
What i want is to skip the row when it gets again to Peter, and select the next result, in our case Adam. So i don't want to show my visitors that the recently active users were Laura, Tom, Josh, Peter, and Peter again. That does not make any sense, instead i want to show them this way: Laura, Tom, Josh, Peter, (skipping Peter) and Adam.
Is there an SQL command i can use for this problem?
Yes. "DISTINCT".
SELECT DISTINCT(user_id) FROM messages ORDER BY id DESC LIMIT 5
Maybe you could exclude duplicate user using GROUP BY.
SELECT * FROM messages GROUP BY user_id ORDER BY id DESC LIMIT 5;