Replicate recent location - sql

I have table like below
ID User Date Location
1 Tom 6-Mar-2012 US
2 Tom 4-Feb-2012 UK
3 Tom 6-Jan-2012 Uk
4 Bob 6-Mar-2012 UK
5 Bob 4-Feb-2012 UK
6 Bob 6-Jan-2012 AUS
7 Dev 6-Mar-2012 US
8 Dev 4-Feb-2012 AUS
9 Nic 6-Jan-2012 US
I have to get each employee recent location in same table.
ID User Date Location CurrentLocation
1 Tom 6-Mar-2012 US US
2 Tom 4-Feb-2012 UK US
3 Tom 6-Jan-2012 Uk US
4 Bob 6-Mar-2012 UK UK
5 Bob 4-Feb-2012 UK UK
6 Bob 6-Jan-2012 AUS UK
7 Dev 6-Mar-2012 US US
8 Dev 4-Feb-2012 AUS US
9 Nic 6-Jan-2012 US US
I have tired with temp tables. can I get this done using single query. This is in middle of implementation. I have already created many temp tables.
Thanks in Advance.

Try this:
select *, CurrentLocation
from tbl x
outer apply
(
select top 1 location as CurrentLocation
from tbl
where [user] = x.[user]
and id <= x.id
order by id
) y
order by id
Output:
ID USER DATE LOCATION CURRENTLOCATION
1 Tom 2012-03-06 US US
2 Tom 2012-02-04 UK US
3 Tom 2012-01-06 Uk US
4 Bob 2012-03-06 UK UK
5 Bob 2012-02-04 UK UK
6 Bob 2012-01-06 AUS UK
7 Dev 2012-03-06 US US
8 Dev 2012-02-04 AUS US
9 Nic 2012-01-06 US US
Live test: http://www.sqlfiddle.com/#!3/83a6a/7

select
id,
user,
date,
location,
first_value(location) over(partition by user order by date desc) as current_location
from your_table s;
The above is valid only in Oracle.
This is my try in absence of first_value analytic function:
select
a.id,
a.usr,
a.date,
a.location,
m.location as current_location
from
a
join
(select usr, location
from
(select usr,
location,
row_number() over(partition by usr order by date desc) as rnk
from a
)b
where rnk = 1) m
on m.usr = a.usr;
The m inner query contains the records with most recent user entries.
After this I make a join with this view, to obtain users's location.
See here sqlfiddle test.

Related

How do I display rows from a max count?

I want to return all the data, from max count query with hospital that has most number of patients. What I seem to be getting when I try to nest queries is display of all rows of hospital data. I've tried to look at similar questions in stack overflow and other sites it seems to be a simple query to do but i am not getting it.
select max(highest_hospital) as max_hospital
from (select count(hospital) as highest_hospital
from doctor
group by hospital)
highest_hospital
-------------
3
Doc ID Doctor Patient Hospital Medicine Cost
------ ------- ------ --------- ------ --------
1 Jim Bob Patient1 Town 1 Medicine 1 4000
2 Janice Smith Patient2 Town 2 Medicine 3 3000
3 Harold Brown Patient3 Town 2 Medicine 5 2000
4 Larry Owens Patient4 Town 2 Medicine 6 3000
5 Sally Brown Patient5 Town 3 Medicine 7 4000
6 Bob Jim Patient6 Town 4 Medicine 8 6000
Outcome should be return of 3 rows
Doc ID Doctor Patient Hospital Medicine Cost
------ ------- ------ --------- ------ --------
2 Janice Smith Patient2 Town 2 Medicine 3 3000
3 Harold Brown Patient3 Town 2 Medicine 5 2000
4 Larry Owens Patient4 Town 2 Medicine 6 3000
You can use window functions:
select d.*
from (select d.*, max(hospital_count) over () as max_hospital_count
from (select d.*, count(*) over (partition by hospital) as hospital_count
from doctor d
) d
) d
where hospital_count = max_hospital_count;
Edit:
Using GROUP BY is a pain. If you are only looking for a single hospital (even when there are ties), then in Oracle 12C you can do:
select d.*
from doctor d
where d.hospital = (select d2.hospital
from doctor d2
group by d2.hospital
order by count(*) desc
fetch first 1 row only
);
You can do this in earlier versions of Oracle using an additional subquery.

SQL query to get only rows match the condition based on two separated columns under one 'group by'

The simple SELECT query would return the data as below:
Select ID, User, Country, TimeLogged from Data
ID User Country TimeLogged
1 Samantha SCO 10
1 John UK 5
1 Andrew NZL 15
2 John UK 20
3 Mark UK 10
3 Mark UK 20
3 Steven UK 10
3 Andrew NZL 15
3 Sharon IRL 5
4 Andrew NZL 25
4 Michael AUS 5
5 Jessica USA 30
I would like to return a sum of time logged for each user grouped by ID
But for only ID numbers where both of these values Country = UK and User = Andrew are included within their rows.
So the output in the above example would be
ID User Country TimeLogged
1 John UK 5
1 Andrew NZL 15
3 Mark UK 30
3 Steven UK 10
3 Andrew NZL 15
First you need to identify which IDs you're going to be returning
SELECT ID FROM MyTable WHERE Country='UK'
INTERSECT
SELECT ID FROM MyTable WHERE [User]='Andrew';
and based on that, you can then filter to aggregate the expected rows.
SELECT ID,
[User],
Country,
SUM(Timelogged) as Timelogged
FROM mytable
WHERE (Country='UK' OR [User]='Andrew')
AND ID IN( SELECT ID FROM MyTable WHERE Country='UK'
INTERSECT
SELECT ID FROM MyTable WHERE [User]='Andrew')
GROUP BY ID, [User], country;
So, you have described what you need to write almost perfectly but not quite. Your result table indicates that you want Country = UK OR User = Andrew, rather than AND
You need to select and group by, then include a WHERE:-
Select ID, User, Country, SUM(Timelogged) as Timelogged from mytable
WHERE Country='UK' OR User='Andrew'
Group by ID, user, country

How to add an independent column into a query result

I try to googling for this issue and still couldn't find the solution.
I have 2 column to combine like below:
First table:
ID Name Item
42 america 1433
42 america 1695
42 america 1234
8 london 1433
8 london 1705
8 london 1432
Second table:
ID CreatedBy
42 John
42 Erica
8 Amy Song
8 Alfred
If I just join both table it will become like this:
ID Name Item CreatedBy
42 america 1433 John
42 america 1695 John
42 america 1234 John
42 america 1433 Erica
42 america 1695 Erica
42 america 1234 Erica
8 london 1433 Amy Song
8 london 1705 Amy Song
8 london 1432 Amy Song
8 london 1433 Alfred
8 london 1705 Alfred
8 london 1432 Alfred
Column Created By is only related to ID, and not related to Name and Item.
I just want to insert CreatedBy as a new column into first table that only linked to ID, so the expected result will be like below.
Is there any way I could get result like this?
ID Name Item CreatedBy
42 america 1433 John
42 america 1695 Erica
42 america 1234 NULL
8 london 1433 Amy Song
8 london 1705 Alfred
8 london 1432 NULL
Let say we change second table like this:
Second table:
ID CreatedBy
42 John
8 Amy Song
Result will be like this:
ID Name Item CreatedBy
42 america 1433 John
42 america 1695 NULL
42 america 1234 NULL
8 london 1433 Amy Song
8 london 1705 NULL
8 london 1432 NULL
I really apreacite for your help, and thank you in advanced masta.
NOTE: Column CreatedBy is the independent column that only relate to ID and not relate to Name and Item.
So, I will answer you even though some guys that discussed it here on comments may disagree as there is no a proper logic to your problem.
It is important to note that this answer is for this SPECIFIC case if it won't get you the right data for a larger dataset you have to provide more info on it.
What I did:
I've created a subset from the first set ordering it (and indexing it, window function) by the name then I created another subset from the second set ordering it by the id so, i have:
select id, name, item, row_number() over (partition by name order by name) idx from tablea
And
select id, createdby, row_number() over (partition by id order by id) idx from tableb
Then I LEFT JOIN the tablea with tableb by the id and the order created colum idx so
select a.id, a.name, a.item, b.createdby
from (select id, name, item, row_number() over (partition by name order by name) idx from tablea) a
left join
(select id, createdby, row_number() over (partition by id order by id) idx from tableb) b
on (a.id = b.id and a.idx=b.idx)
order by a.name
The order by is just to get the result as you asked on your question.
See it here: http://sqlfiddle.com/#!3/7ef70/3
For your second sample data: http://sqlfiddle.com/#!3/675625/1

Limiting records of combinations from 2 columns

looking for some help limiting the results while querying combinations between 2 columns. Here's an example of the kind of table I am working with..
id name group state
1 Bob A NY
2 Jim A NY
3 Dan A NY
4 Mike A FL
5 Tim B NY
6 Sam B FL
7 Brad B FL
8 Glen B FL
9 Ben C FL
I am trying to display all records of all combinations of "group" and "state", but limiting to displaying only up to 2 records for each combination. The result should look like the following..
id name group state
1 Bob A NY
2 Jim A NY
4 Mike A FL
5 Tim B NY
6 Sam B FL
7 Brad B FL
9 Ben C FL
Thanks for the help.
Assuming you always want the two rows for each group and state combination with the lowest id
SELECT *
FROM (SELECT a.*,
row_number() over (partition by group, state
order by id asc) rnk
FROM your_table a)
WHERE rnk <= 2
Of course, since group is a reserved word, I assume your column is actually named something else... You'd need to adjust my query to use the correct column name.

Problem with GROUP BY statement (SQL)

I have a table GAMES with this information:
Id_Game Id_Player1 Id_Player2 Week
--------------------------------------
1211 Peter John 2
1215 John Louis 13
1216 Louis Peter 17
I would like to get a list of the last week when each player has played, and the number of games, which should be this:
Id_Player Week numberGames
-----------------------------
Peter 17 2
John 13 2
Louis 17 2
But instead I get this one (notice on Peter week):
Id_Player Week numberGames
-----------------------------
Peter 2 2
John 13 2
Louis 17 2
What I do is this:
SELECT Id_Player,
MAX(Week) AS Week,
COUNT(*) as numberGames
FROM ((SELECT Id_Player1 as Id_Player, Week
FROM Games)
UNION ALL
(SELECT Id_Player2 as Id_Player, Week
FROM Games)) AS g2
GROUP BY Id_Player;
Could anyone help me to find the mistake?
What is the datatype of the Week column? If the datatype of Week is varchar you would get this behavior.