I would like to know what would be the best way to get the data from a specific row when I use a Group By query. The real query is more complex than the example I'm providing here so I'm looking for something other than a sub-select on the Sales table.
I'm using MSSQL 2008 and I would like something that allow me to get the date field from the Sales record that has the max(amount).
Query
select uid, firstName, lastName, AmountFromTagetedRow, DateFromTargetedRow,
from users u inner join
sales s on u.uid = s.custID
group by uid, firstName, lastName
order by uid
USERS
uid firstName lastName
1 Sam Smith
2 Joe Brown
3 Kim Young
SALES
sid Custid date amount ...
1 1 2016-01-02 100
2 3 2016-01-12 485
3 1 2016-01-22 152
4 2 2016-02-01 156
5 1 2016-02-02 12
6 1 2016-03-05 84
7 2 2016-03-10 68
RESULTS
uid firstName LastName amount date
1 Sam Smith 152 2016-01-22
2 Joe Brown 156 2016-02-01
3 Kim Young 485 2016-01-12
Your posted query doesn't match your amount but something like this should get you pointed in the right direction.
with SortedResults as
(
select uid
, firstName
, lastName
, AmountFromTagetedRow
, DateFromTargetedRow
, ROW_NUMBER() over (partition by u.uid order by AmountFromTagetedRow desc) as RowNum
from users u inner join
sales s on u.uid = s.custID
group by uid
, firstName
, lastName
)
select *
from SortedResults
where RowNum = 1
order by uid
Related
I have 2 simple tables as follows:-
Student
---------------------------------------------
student_id student_name student_class
107 paul A Level-I
108 susan Diploma
109 jack O Level-II
---------------------------------------------
Student_Positions
--------------------------------------------------
position_id student_id position date
1 107 1 1-1-2020
2 107 1 1-1-2021
3 109 2 1-1-2021
4 109 1 1-6-2019
I want a left outer join on these tables for the latest position of every student as fol:-
student_id student_name position date
107 paul 1 1-1-2021
108 susan
109 jack 2 1-1-2021
I have made multiple tries with different positions of max(date) and group by but in vain.
Please help with correct query
The canonical SQL solution uses a window function such as row_number():
select s.*, sp.position, sp.date
from students s left join
(select sp.*,
row_number() over (partition by student_id order by date desc) as seqnum
from student_positions sp
) sp
on sp.student_id = s.student_id and sp.seqnum = 1;
I have two table User and Score, each user have multiple score. How can I query average score with user name:
Ex:
Jack 6
Sham 5
User
Name user_id
Jack 123
Tony 234
Sham 456
Score
id score user_id
1 4 123
2 8 123
3 9 234
4 2 456
5 10 456
6 3 456
If I understand, this is a join and group by:
select u.name, avg(s.score)
from users u join
scores s
using (user_id)
group by user_id, u.name;
Note that I've included user_id in the group by, in case two users have the same name.
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
My problem right now is that I need to make an statement where select all rows that are duplicates with specific needs.
For example I got table 1 (users):
Users:
----------------------------------------------
ID name lastname birth file number
1 Max Lix 2015-02-01 D43-892
2 Chris Maura 2010-12-25 E33-722
4 Lena Paul 2005-05-11 S85-458
5 Max Lix 2019-02-01 D23-992
6 Lena Paul 2005-05-11 S84-488
7 Lena Paul 2005-05-11 S75-258
----------------------------------------------
Address(u_ID = ID of Users table):
----------------------------------------------
ID u_ID Street number zip
1 1 Heystr. 12 4556
2 2 Nostr. 2 8978
3 4 Yesstr. 8a 2545
I need to get all rows where the name, lastname and birth does match with other rows and also get the address for that person.
The result should look like this:
Result:
----------------------------------------------
name lastname birth filenumber address
Max Lix 2015-02-01 D43-892 Heystr. 12 4556
Max Lix 2019-02-01 D23-992 Heystr. 12 4556
Lena Paul 2005-05-11 S85-458 Yesstr. 8a 2545
Lena Paul 2005-05-11 S84-488 Yesstr. 8a 2545
Lena Paul 2005-05-11 S75-258 Yesstr. 8a 2545
The first idea that I had was to use GROUP BY and HAVING but that does only return one row but I need every single duplicate matching the name, lastname and birth.
Use this:
select u.name, u.lastname, u.birth, u.filenumber, concat(a.street, ' ', a.number, ' ', a.zip) address
from users u
left join address a
on a.u_id = u.id
where
exists (
select 1 from users
where users.name = u.name and user.lastname = u.lastname and user.birth = u.birth and users.id <> u.id
)
With the condition:
users.name = u.name and user.lastname = u.lastname and user.birth = u.birth and users.id <> u.id
you can find the dupilcates.
Use inner join instead of left join if you want the duplicates only once.
SELECT name, lastname, birth, filenumber, concat(street,' ' , number, ' ', zip) as address
FROM Users A, Adress
WHERE u_id = a.id
AND (SELECT COUNT(1)
FROM Users B
WHERE A.name = B.name
AND A.lastname = B.lastname) > 1
with duplicate as ( -- this CTE makes a list of duplicated user_IDs
Select u.id
from users
group by name, lastname, birth
having count(*) >= 2
)
Select concat(street,' ' , number, ' ', zip) as address,
name, lastname, birth, filenumber
from duplicates d -- gather the data
join addresses on d.id=uid
join users on u.id=d.uid
will return you a report of all the people having an homonym with same birthday
Please try below,
select U.name,U.lastname,U.birth,U.filenumber,concat(street,' ',number,' ',zip) as address
from Users U join Address A on
U.ID=A.u_Id
group by name,lastname,birth
having count(*)>1
I have two tables
Schedule:
scheduleID DriverID ScheduleDate
11 1 2015-05-20
22 2 2015-05-20
33 NULL 2015-05-21
44 NULL 2015-05-21
and
Employee:
ID Fname Lname
1 jack miller
2 kelly moore
3 mark sam
4 tom hanks
I want to select from these two tables based on ScheduleDate and show the driver full name from Employee table and show null columns.
The result should be like:
scheduleID Fname Lname
33 NULL NULL
44 NULL NULL
I used:
select row_number() over (order by scheduleID desc) as schedule, scheduleID, Driver_ID,FirstName,LastName
From Schedule, Employee
where scheduleDate= '2015-05-21' AND EmployeID=Driver_ID;
It works well if " scheduleDate= '2015-05-20' "
but I need to show null Columns too!
any help!
You need a left join for this -- just emphasizing why you should never using implicit join syntax. Simple rule: Always use explicit join syntax. Never use commas in the from clause.
select row_number() over (order by scheduleID desc) as schedule, scheduleID,
Driver_ID, FirstName, LastName
From Schedule left join
Employee
on EmployeID = Driver_ID
where scheduleDate = '2015-05-21';