I have 3 tables:
user(id, name, id_school)
school(id, name)
result(id_user, stage1, stage2)
Now I would like to get school ranking - is sum of 2 columns: stage1 and stage2 of all users.
seems too simple:
select s.name as school, sum(stage1)+sum(stage2) as rank
from result r
join user u on u.id=r.id_user
join school s on s.id=u.id_school
group by s.id
and i really hope you have indexes.
Try this query. It is only assumption.please provide some data for testing
SELECT
s.id,
s.name AS SchoolName
(r.S1 + r.S2) AS Rank
FROM school as s
LEFT JOIN user as u ON u.id_school = s.id
LEFT JOIN (SELECT id_user , SUM(stage1) as S1 , SUM(stage2) FROM result GROUP BY id_user) as r ON r.id_user = u.id
GROUP BY s.id
ORDER BY Rank DESC
I would do something like this:
SELECT school.name, SUM(result.result1 + result.result2)
FROM school LEFT JOIN user ON (user.id_school = school.id) LEFT JOIN result ON (result.id_user = user.id) GROUP BY school.id
Hope it helps, good luck :)
Related
I am trying to make a query to fetch the newest car for each user:
select * from users
left join
(select cars.* from cars
where cars.userid=users.userid
order by cars.year desc limit 1) as cars
on cars.userid=users.userid
It looks like it says Unknown column "users.userid" in where clause
I tried to remove cars.userid=users.userid part, but then it only fetches 1 newest car, and sticks it on to each user.
Is there any way to accomplish what I'm after? thanks!!
For this purpose, I usually use row_number():
select *
from users u left join
(select c.* , row_number() over (partition by c.userid order by c.year desc) as seqnum
from cars c
) c
on c.userid = u.userid and c.seqnum = 1;
One option is to filter the left join with a subquery:
select * -- better enumerate the columns here
from users u
left join cars c
on c.userid = u.userid
and c.year = (select max(c1.year) from cars c1 where c1.userid = c.userid)
For performance, consider an index on car(userid, year).
Note that this might return multiple cars per user if you have duplicate (userid, year) in cars. It would be better to have a real date rather than just the year.
Maybe there are better and more efficient way to query this. Here is my solution;
select users.userid, cars.*
from users
left join cars on cars.userid = users.userid
join (SELECT userid, MAX(year) AS maxDate
FROM cars
GROUP BY userid) as sub on cars.year = sub.maxDate;
I have a MySQL query which I want to execute to see who is the employee with the best skill X in a company I work for. To do this I randomly pick a company from my cv_profile (skill_cv_test) and find all users who work there for the same employer. And then I randomly choose a skill I have.
The result should either be zero or a list.
But when testing with PHPMyAdmin I get results where I don't see any row, but the status says there is at least one row.
Here's an example of the message I get: https://imgur.com/bVMH716
I have been trying different structures, even "walling" the query with another query, different joins.
SELECT
DISTINCT(sv.usr_id),
u.first_name AS fn,
u.last_name AS ln,
c.name AS company,
s.name AS skill
FROM
(
SELECT
MAX(last_change) as date,
id,
usr_id,
skill_id
FROM skill_valuations
GROUP BY usr_id, skill_id
ORDER BY date
) sv
LEFT JOIN skill_valuations skv ON skv.last_change = sv.date
INNER JOIN
(
SELECT
DISTINCT(skct.comp_id),
skct.usr_id AS usr_id,
skct.category
FROM skill_cv_test skct
WHERE skct.end_date IS NULL AND skct.comp_id IN (SELECT comp_id FROM (SELECT comp_id FROM skill_cv_test WHERE usr_id = 1 ORDER BY RAND() LIMIT 1) x)
) uqv ON uqv.usr_id = sv.usr_id
INNER JOIN
(
SELECT skill_id
FROM usr_skills
WHERE usr_id = $uid
ORDER BY RAND()
LIMIT 1
) usq ON usq.skill_id = sv.skill_id
LEFT JOIN companies c ON c.id = uqv.comp_id
LEFT JOIN skills s ON s.id = sv.skill_id
LEFT JOIN users u ON u.id = sv.usr_id
As mentioned before, I expect either no results or a result of at least one row.
I want each student's name, last payment date only. means only day.
I know i won't help you at all giving this code:
But you could try to learn something from it.
SELECT S.Id, S.Name, F.max_date, F.FeeAmt
FROM tbl_student As S
INNER JOIN (
SELECT t.Id, MAX(t.Date) As max_date, t.FeeAmt FROM tbl_fees As t GROUP BY t.Id
) As F ON F.Id=S.Id
First we selected all users from tbl_student, and then we are joining fees, selecting max date and grouping by user. The result is last (date) fee per user.
Please try this query. I hope this should give you the expected output:
SELECT S.Name, T1.LastPaymentDate
FROM
(SELECT Id, Max([Date]) AS LastPaymentDate from tbl_fees GROUP BY Id) AS T1
INNER JOIN
tbl_student AS S
ON T1.Id = S.Id
SELECT S.name,SUB.LAST_DATE
FROM tbl_student S
JOIN (SELECT f.id AS ID,MAX(f.Date) AS LAST_DATE
FROM tbl_fees f
GROUP BY f.id) SUB
ON SUB.id = S.id
I'm using MySQL and MSSql and I'm trying to join these two queries together.
Query 1
(SELECT REP.REP_NUM, REP.FIRST_NAME, REP.LAST_NAME
FROM REP, CUSTOMER)
Query 2
(SELECT CUSTOMER.REP_NUM, SUM(CUSTOMER.BALANCE) AS REP_BALANCE
FROM CUSTOMER
GROUP BY CUSTOMER.REP_NUM)
I've seen you can treat these as two Tables and join them but I'm having trouble getting it to work. The way I was trying to join them I'd get aggregate errors from trying to select the rep first and last name while using the balance sum.
Thanks in advance!
SELECT R.REP_NUM, R.FIRST_NAME, R.LAST_NAME
FROM REP r
inner join
(SELECT c.REP_NUM, SUM(c.BALANCE) AS REP_BALANCE
FROM CUSTOMER c
GROUP BY c.REP_NUM) t
on r.rep_num = t.rep_num
SELECT r.REP_NUM, r.FIRST_NAME, r.LAST_NAME, SUM (c.BALANCE) AS REP_BALANCE
FROM REP r
INNER JOIN CUSTOMER c ON r.REP_NUM = c.REP_NUM
GROUP BY r.REP_NUM, r.FIRST_NAME, r.LAST_NAME
try this:
SELECT REP.REP_NUM, REP.FIRST_NAME, REP.LAST_NAME
FROM REP join(
SELECT CUSTOMER.REP_NUM, SUM(CUSTOMER.BALANCE) AS REP_BALANCE
FROM CUSTOMER
GROUP BY CUSTOMER.REP_NUM
) as B on some_condition...
try it
select a.REP_NUM,a.FIRST_NAME,a.LAST_NAME,b.REP_NUM,Sum(b.BALANCE) as REP_BALANCE from REP a as inner join CUSTOMER b on a.REP_NUM=b.REP_NUM group by b.REP_NUM
Select New.REP_NUM,New.FIRST_NAME,New.LAST_NAME,CUSTOMER.REP_NUM,
SUM(CUSTOMER.BALANCE) AS REP_BALANCE
from (SELECT REP.REP_NUM, REP.FIRST_NAME, REP.LAST_NAME
FROM REP, CUSTOMER) New
inner join CUSTOMER ON CUSTOMER.REP_NUM=New.REP_NUM
GROUP BY CUSTOMER.REP_NUM
Okay I tried to look all over stackoverflow, and the closest solution I found is this:
mysql AND clause on same column multiple times
But I can't use statements and "having" syntax won't work because of group by. There MUST be a simple solution to this.
The 2 tables looks like this (simplified):
users:
uid name
1 person 1
2 person 2
3 person 3
categories:
uid value
1 actor
1 musician
2 actor
3 dancer
4 musician
4 dancer
I want to get the uid of those that are 2 values at the same time. For example, I want to get the UID that is an actor AND a musician. Not just one value, but both of them must be required!
First I tried this:
SELECT users.uid, users.name
FROM
users
LEFT OUTER JOIN categories ON users.uid = categories.uid
WHERE (categories.value = 'actor' AND categories.value = 'musician')
GROUP BY u.uid;
This of course does not work since one row can't have 2 values.
Does anyone know a solution?
You can JOIN to the categories table multiple times to get the result:
SELECT users.uid, users.name
FROM users
INNER JOIN categories c1
ON users.uid = c1.uid
INNER JOIN categories c2
ON users.uid = c2.uid
WHERE c1.value = 'actor'
AND c2.value = 'musician';
See SQL Fiddle with Demo
SELECT users.uid, users.name
FROM users
LEFT JOIN categories ON users.uid = categories.uid
WHERE categories.value in ('actor', 'musician')
GROUP BY u.uid, users.name
having count(distinct categories.value) = 2;
Use a having clause
SELECT u.uid, u.name
FROM users u
LEFT OUTER JOIN categories c ON u.uid = c.uid
WHERE c.value = 'actor' OR c.value = 'musician'
GROUP BY u.uid
having count(distinct c.value) > 1
If you really do not want to use having you could try this:
SELECT uid, name
FROM users
WHERE
uid IN (SELECT uid FROM categories WHERE value='actor')
AND uid IN (SELECT uid FROM categories WHERE value='musician')
But there is really nothing wrong with using HAVING ;)