Contest
contest_id Launched name
-------------------------------------------------------------------------
1 0 Cont1
2 1 cont2
participants
participants_id group_id contest_id puser_id
-------------------------------------------------------------------------
1 1 1 555
2 1 1 666
fusers
fuser_id name
-------------------
555 Alex
666 sabrina
I need to write up a query that will select all users(name,groupid,contestname) who are participants of all contests
Details of all users are in fusers, where as contest has all contest hosted Launched should be 1 and participants is the table that contains id of users who have decided to participate in a contest.
fuser_id = puser_id
Want to find who is participating in contest_id=1 there group_id,contestname and name
Your description is not particularly legible, but I think this is what you want.
SELECT fusers.fuser_id, fusers.name, Contest.contest_id, Contest.name
FROM fusers
LEFT JOIN participants ON fusers.fuser_id = participants.participants_id
LEFT JOIN Contest ON Contest.contest_id = participants.contest_id
WHERE (Contest.Launched = 1)
From what I understand:
SELECT f.name, p.group_id, c.name contestName
FROM
participants p
JOIN fusers u on p.puser_id=u.fuser_id
JOIN contest c on p.contest_id = c.contest_id
WHERE c.launched = 1
AND c.contest_id = 1 /*or any other contest_id*/
Related
I am working on a system where we have customer data split up across a variety of tables. As an example (simplified):
Customer Status
id
name
status
1
Stan
active
2
Danny
closed
3
Elle
active
4
Stan
active
Account Status
id
name
status
1
Stan
good standing
2
Danny
good standing
3
Elle
good standing
4
Stan
in arrears
5
Stan
good standing
6
Elle
in arrears
Order Status
id
name
status
1
Stan
Ordered
2
Danny
Ordered
3
Elle
Pending
4
Stan
Completed
5
Stan
Pending
6
Elle
Ordered
If I wanted to identify all customers that are:
Customer Status: Active
Account Status: In arrears
Order Status: Pending
In the above example, the only returned name should be Stan
I've been attempting SQL such as this, but realised it's selecting not the max, but the max that has my filter:
SELECT * FROM customer_status c
WHERE c.id = (SELECT MAX(c2.id) FROM customer_status c2 WHERE c2.name = c.name) AND c.status = "active"
AND c.name in (SELECT name FROM account_status as WHERE as.id = (SELECT MAX(as2.id) FROM account_status as2 WHERE as.name = as2.name) AND as.active = "in arrears")
AND c.name in (SELECT name FROM order_status os WHERE os.id = (SELECT MAX(os.id) FROM order_status os2 WHERE os.name = os2.name) AND os.status = "Pending")
What I've realised is that the rows being returned for account status and order status is the highest ID with the provided status, whereas I'd like to get the last row for each customer and then only pass them back if they have the right status.
Is this where I need to use Joins instead?
You can make a simple join like this:
SELECT * FROM customer_status c
INNER JOIN account_status as ON c.name = as.name
INNER JOIN order_status os ON c.name = os.name
WHERE c.status = "active"
AND as.active = "in arrears"
AND os.status = "Pending"
I have persons i one table [person] and cars [car] registered to each person i another, connected by id.
I want to get a list of how many persons having how many cars.
Something like this:
PERSON
id
name
1
LISA
2
ADAM
3
RAY
CARS
id
id_person
brand
1
3
FORD
2
1
BMW
3
2
VOLVO
4
1
VOLVO
5
1
VW
RESULT
no cars
no persons
1
2
2
0
3
1
Just dont get how to do it?
You need to do it in two stages. The first is to get the number of cars per person -
SELECT p.id, COUNT(*) num_cars
FROM person p
JOIN cars c ON p.id = c.id_person
GROUP BY p.id
This can then be nested to count people per count -
SELECT num_cars, COUNT(*) num_people
FROM (
SELECT p.id, COUNT(*) num_cars
FROM person p
JOIN cars c ON p.id = c.id_person
GROUP BY p.id
) t
GROUP BY num_cars
ORDER BY num_cars ASC
I have the following tables
user
id
name
1
John
2
Jack
3
George
essay
id
date_submitted
user_id
project_id
1
2020-12-10
1
1
2
2020-05-01
2
2
3
2020-04-10
3
2
project_phase
id
project_id
date
phase
1
1
2020-01-01
early
2
1
2020-05-31
mid
3
1
2020-11-30
late
4
2
2020-01-01
early
5
2
2020-03-31
mid
6
2
2020-04-30
late
1 User submits only 1 essay in one project
and I want to have a combined table which shows me the user and the phase at which the essay was submitted.
I'm trying to get the record with the MAX date from project_phase that is below the date_submitted
So using the above data I want to get
user
date_submitted
phase
John
2020-12-10
late
Jack
2020-05-01
late
George
2020-04-10
mid
so far I combined the tables with INNER JOIN but the following query returns duplicate records. I also tried ROW_NUMBER() and MAX() but I didn't structure it correctly to get the answer I'm looking for
SELECT
U.name,
E.date_submitted,
P.phase
FROM
essay E
INNER JOIN user U ON U.id = E.user_id
INNER JOIN project_phase P ON P.project_id = E.project_id and E.date <= P.date_submitted
Any help appreciated, thanks.
I would suggest a correlated subquery:
SELECT U.name, E.date_submitted,
(SELECT P.phase
FROM project_phase P
WHERE P.project_id = E.project_id AND
P.date <= E.date_submitted
ORDER BY p.date DESC
LIMIT 1
) as phase
FROM essay E JOIN
user U
ON U.id = E.user_id;
I have four tables detailing an amusement park and its guests' ride history.
Categories
c_id name
1 Thrill
2 Leisure
3 Kiddie
Rides
r_id c_id
1 1
2 1
3 2
4 2
5 3
6 3
guest_history
h_id g_id
1 1
2 1
3 2
4 3
history_items
h_id r_id
1 5
2 6
3 1
3 2
4 5
How would I get all of the guests (g_id's) that have either rode all of the kiddie rides or none of the kiddie rides?
Expected Output would be:
g_id
1
2
I can't seem to figure out what the easiest way to go about it would be. I can only seem to conjure up a table that contains all of the cases that a guest has rode a kiddie ride. My attempt was a 4-way inner join of the tables and to filter out on the c_id = "Kiddie". Any help would be appreciated.
You can try this below logic-
3 is fixed in the query to get category "Kiddie"
DEMO HERE
SELECT A.g_id,COUNT(C.r_id)
FROM guest_history A
INNER JOIN history_items B ON A.h_id = B.h_id
INNER JOIN Rides C ON B.r_id = C.r_id AND C.c_id = 3
GROUP BY A.g_id
HAVING COUNT(DISTINCT B.r_id) = (SELECT COUNT(r_id) FROM Rides WHERE c_id = 3)
OR COUNT(DISTINCT B.r_id) = 0
SELECT g_id
FROM Categories
NATURAL JOIN Rides
NATURAL JOIN guest_history
NATURAL JOIN history_items
GROUP BY g_id
HAVING COUNT(DISTINCT r_id) IN (0,
(SELECT COUNT(DISTINCT r_id)
FROM Categories
NATURAL JOIN Rides
WHERE name = 'Kiddie')
)
fiddle
(Using mysql 5.0)
I have this table:
opportunity main_user_id certificate_id required_certificates
1 491 1 2
1 341 1 2
1 161 1 2
1 161 2 2
1 205 2 2
1 578 2 2
2 161 2 2
2 466 3 2
2 466 2 2
2 156 2 2
2 668 2 2
3 222 5 1
3 123 5 1
3 875 5 1
3 348 5 1
I need to only display the rows where number of distinct values in certificate_id equals value in required_certificates.
opportunity_id column has id's from 0 to 15 and main_user_id's repeat (hence I can't use group by)
The table is basically a list of users matched for particular job opportunity, who have the required certificates. All i need to do now, is to only show the ones who have both of the required certificates, not one OR another.
My current sql statement:
select op_main.id as opportunity_id, u.id as main_user_id, c.id as certificate_id, required2.required as required_certificates
from opportunities as op_main
join opportunity_certificates as oc on oc.opportunity_id = op_main.id
join certificates as c on c.id = oc.certificate_id and oc.is_required
join user_certificates as uc on uc.certificate_id = c.id
join users as u on u.id = uc.user_id
join (
select id as op_id, (
select count(distinct c.id)
from opportunities as op
join opportunity_certificates as oc on oc.opportunity_id = op.id
join certificates as c on c.id = oc.certificate_id and oc.is_required
join user_certificates as uc on uc.certificate_id = c.id
join users as u on u.id = uc.user_id
where uc.certificate_id = oc.certificate_id and oc.is_required and op.id = op_id
) as required from opportunities
) as required2 on required2.op_id = op_main.id
where uc.certificate_id = oc.certificate_id and oc.is_required and op_id = op_main.id
based on the table above the output would be:
opportunity main_user_id
1 161
2 466
3 222
3 123
3 875
3 348
I spent many hours trying to work it out. If someone is keen on helping me, I can send you the database. Thanks.
It is quite simple with windowed functions - MySQL 8 and above:
WITH cte AS (
SELECT *, COUNT(DISTINCT certificate_id) OVER(PARTITION BY user_id) AS cnt
FROM (
-- your query with joins
) sub
)
SELECT *
FROM cte
WHERE cnt = required_certificates;
DBFiddle Demo
It turns out that MySQL 8.0 doesn't support COUNT(DISTINCT ...) OVER so I used subquery with DISTINCT.
ER_NOT_SUPPORTED_YET: This version of MySQL doesn't yet support '(DISTINCT ..)'