I want combine multiple query become 1:
SELECT b.fname FROM almanak as a
JOIN users as b on (b.userid = a.staf1)
SELECT c.fname FROM almanak as a
JOIN users as c on (c.userid = a.staf2)
SELECT d.fname FROM almanak as a
JOIN users as d on (d.userid = a.staf3)
SELECT e.fname FROM almanak as a
JOIN users as e on (e.userid = a.staf4)
SELECT f.fname FROM almanak as a
JOIN users as f on (f.userid = a.staf5)
i want make every field userid will select fname field at another table
Here is one way to do it:
SELECT
b.fname fname1,
c.fname fname2,
d.fname fname3,
e.fname fname4,
f.fname fname5
FROM almanak as a
INNER JOIN users as b ON b.userid = a.staf1
INNER JOIN users as c ON c.userid = a.staf2
INNER JOIN users as d ON d.userid = a.staf3
INNER JOIN users as e ON e.userid = a.staf4
INNER JOIN users as f ON f.userid = a.staf5
If there might be missing relations, you can turn the INNER JOINs to LEFT JOINs.
Alternatively, you can do conditional aggregation. Assuming that the primary key of the almanak table is id, that would look like:
SELECT
MAX(CASE WHEN u.userid = a.staf1 THEN u.fname END) fname1,
MAX(CASE WHEN u.userid = a.staf2 THEN u.fname END) fname2,
MAX(CASE WHEN u.userid = a.staf3 THEN u.fname END) fname3,
MAX(CASE WHEN u.userid = a.staf4 THEN u.fname END) fname4,
MAX(CASE WHEN u.userid = a.staf5 THEN u.fname END) fname5
FROM almanak as a
INNER JOIN users as u
ON u.userid IN (a.staf1, a.staf2, a.staf3, a.staf4, a.staf5)
GROUP BY a.id
Related
For a swimming school, parents pay tuition fees for their kids. On a monthly basis, I need to collect the payable fees from a table that holds open balances, but only if their child is marked as 'active'. Here is the catch: an open balance for an "inactive child" is also considered payable IF at least one other child in the same family is marked active.
I have the following MySQL query:
SELECT sum(b.amount) as amount, f.name, u.email
FROM balance b
LEFT JOIN student s ON b.user_id = s.user_id
LEFT JOIN student_family sf ON s.user_id = sf.user_id
LEFT JOIN family f ON sf.fam_id = f.fam_id
LEFT JOIN user u ON u.user_id = s.user_id
WHERE b.status = 'open' AND s.active = 1
GROUP BY u.email
I currently check s.active=1 but this part needs to be adjusted in such as way that we check if there is at least one student in the same family that have active=1.
My attempt (that didn't work):
...
WHERE b.status = 'open' AND ( SELECT max(active) from student s2 LEFT JOIN student_family sf2 ON sf2.user_id = s2.user_id WHERE sf2.fam_id = sf.fam_id ) = 1
How to accomplish this query?
Using the exists clause will resolve the issue:
SELECT sum(b.amount) as amount, f.name, u.email
FROM balance b
LEFT JOIN student s ON b.user_id = s.user_id
LEFT JOIN student_family sf ON s.user_id = sf.user_id
LEFT JOIN family f ON sf.fam_id = f.fam_id
LEFT JOIN user u ON u.user_id = s.user_id
WHERE b.status = 'open' AND exists
(select 1 from student s1
JOIN student_family sf1 ON s1.user_id = sf1.user_id
JOIN family f ON sf1.fam_id = f1.fam_id
where s1.active = 1 and f.fam_id=f1.fam_id)
GROUP BY u.email
You could use a IN clause in your WHERE to see if the student_family.user_id is in a family with at least one active student:
Something like:
SELECT
sum(b.amount) as amount,
f.name,
u.email
FROM
balance b
LEFT JOIN student s ON b.user_id = s.user_id
LEFT JOIN student_family sf ON s.user_id = sf.user_id
LEFT JOIN family f ON sf.fam_id = f.fam_id
LEFT JOIN user u ON u.user_id = s.user_id
WHERE
b.status = 'open'
AND (sf.user_id IN (SELECT sf.user_id FROM student_family sf INNER JOIN student s ON sf.user_id = s.user_id WHERE s.active = 1 GROUP BY sf.user_id ))
GROUP BY
u.email
My current query:
select users.id as user_id, opportunities.id as op_id, opportunities.title, certificates.id as cert_id from opportunities
join opportunity_certificates on opportunities.id=opportunity_certificates.opportunity_id
join certificates on opportunity_certificates.certificate_id=certificates.id
join user_certificates on certificates.id=user_certificates.certificate_id
join users on user_certificates.user_id=users.id
where opportunity_certificates.is_required = 1 and
opportunities.id = 1
This produces the table on the picture below.
cert_id column can have values from 1 to 7, depends on the opportunities.id. In the table below, I want the query to return only the rows which have the same user_id but different cert_id, 1 and 2.
If the table had 3 different cert_id, I would want it to return only the rows which have same user_id but different cert_id, 1,2 and 3.
when the cert_id has only one value, query should return all the records with that one value in cert_id. Basically, it should show all users who have all required certificates.
The query has to be in the current format. I experimented with
group by users.id
having count(*) >
but I don't know how to make that comparison dynamic, relative to the count of distinctive values in the cert_id column.
Compare counts with a having condition.
select u.id as user_id --, o.id as op_id, o.title
from opportunities o
join opportunity_certificates oc on o.id=oc.opportunity_id
join certificates c on oc.certificate_id=c.id
join user_certificates uc on c.id=uc.certificate_id
join users u on uc.user_id=u.id
where oc.is_required = 1 and o.id = 1
group by u.id --,o.id,o.title
having count(distinct c.id)=(select count(distinct id) from certificates)
Useful?
with data as (
select users.id as user_id, o.title, c.id as cert_id
from opportunities o
inner join opportunity_certificates oc on oc.opportunity_id = o.id
inner join certificates c on c.id = oc.certificate_id
inner join user_certificates uc on uc.certificate_id = c.id
inner join users u on u.id = uc.user_id
where oc.is_required = 1 and o.id = 1
)
select user_id, min(title) as title, max(cert_id) as num_certs
from data
group by user_id
having count(cert_id) = (select max(cert_id) from data);
I'm assuming that cert_id values start and 1 and run sequentially. You could also use count(distinct ...) in the having clause but it guess it's debatable which ones expresses you intent more clearly.
If your version of MySQL doesn't support CTEs then you should be able to just drop that whole subquery into the having clause as well.
select u.id as user_id, min(o.title) as title, max(c.cert_id) as num_certs
from opportunities o
inner join opportunity_certificates oc on oc.opportunity_id = o.id
inner join certificates c on c.id = oc.certificate_id
inner join user_certificates uc on uc.certificate_id = c.id
inner join users u on u.id = uc.user_id
where oc.is_required = 1 and o.id = 1
group by u.id
having count(c.cert_id) = (
select max(c.cert_id)
from opportunities o
inner join opportunity_certificates oc on oc.opportunity_id = o.id
inner join certificates c on c.id = oc.certificate_id
inner join user_certificates uc on uc.certificate_id = c.id
inner join users u on u.id = uc.user_id
where oc.is_required = 1 and o.id = 1
);
Here's another one that might work if you have window functions available. (It might work with Laravel better?):
select *
from (
select users.id as user_id, o.title,
count(distinct c.id) over (partition by u.id) as user_certs,
max(c.id) over () as total_certs
from opportunities o
inner join opportunity_certificates oc on oc.opportunity_id = o.id
inner join certificates c on c.id = oc.certificate_id
inner join user_certificates uc on uc.certificate_id = c.id
inner join users u on u.id = uc.user_id
where oc.is_required = 1 and o.id = 1
) t
where user_certs = total_certs;
I want to know how to complete this query correctly.
I wish to export a full list of votes from all ips used by an user.
My database have 3 tables storing the relatives data =>
votes = vote_site_id | vote_ip | vote_time
connexions_ip = adresse_ip | user_id | connexion_time
users = user_id | user_name | user_ip
So actually I have this query to have all connexions_ip from one user =>
SELECT c.adresse_ip, c.user_id, u.user_name
FROM connexions_ip c
LEFT JOIN users u ON u.user_id = c.user_id
WHERE u.user_id = '1'
And this query to have all votes from one user =>
SELECT v.vote_site_id, v.vote_ip, v.vote_time, u.user_name
FROM votes v
LEFT JOIN users u ON u.user_ip = v.vote_ip
WHERE user_id = '1'
I tried with subquery but I have this error "#1242 - Subquery returns more than 1 row"
SELECT v.vote_site_id, v.vote_ip, v.vote_time, u.user_name
FROM votes v
LEFT JOIN users u ON (
SELECT c.adresse_ip
FROM connexions_ip c
LEFT JOIN users u ON u.user_id = c.user_id
WHERE u.user_id = '1'
)
= v.vote_ip
WHERE user_id = '1'
Thanks for your help.
You can join all the table
SELECT c.adresse_ip, c.user_id, u.user_name
, v.vote_site_id, v.vote_ip, v.vote_time
FROM users u
LEFT JOIN connexions_ip c ON u.user_id = c.user_id
LEFT JOIN votes v ON u.user_ip = v.vote_ip
WHERE u.user_id = '1'
I choosed the table users as the base for FROM because is the only table with a condition.
try this:
select a.*,b.* from (SELECT c.adresse_ip, c.user_id, u.user_name
FROM connexions_ip c
LEFT JOIN users u ON u.user_id = c.user_id
WHERE u.user_id = '1')a left join (SELECT u.user_id,v.vote_site_id, v.vote_ip, v.vote_time, u.user_name
FROM votes v
LEFT JOIN users u ON u.user_ip = v.vote_ip
WHERE user_id = '1')b on a.user_id = b.user_id
I have two tables, users and contestants. I'm trying to select the max contestant ID that has a profile picture(which is on the user table)
Heres my terrible SQL:
SELECT u.thumbnail, u.id FROM users AS u
INNER JOIN
(
SELECT c.id, c.user_id FROM contestants AS c
WHERE u.id = c.users_id
AND c.id = (select max(c.id))
) WHERE u.thumbnail IS NOT NULL
The error currently is: #1248 - Every derived table must have its own alias.
This confuses me since Users has an alias of u, and contestants has an alias of c..
What am I doing wrong here? I'm guessing a lot so some help would be really appreciated!
Whenever you are performing a join operation, you are actually joining two table. The subquery you wrote here, for instance, is working as a separate table. Hence, you have to use an alias to this table. That's the reason behind your error message.
Your query:
SELECT u.thumbnail, u.id FROM users AS u
INNER JOIN
(
SELECT c.id, c.user_id FROM contestants AS c
WHERE u.id = c.users_id
AND c.id = (select max(c.id))
) WHERE u.thumbnail IS NOT NULL
It should contain an alias for the subquery:
SELECT c.id, c.user_id FROM contestants AS c
WHERE u.id = c.users_id
AND c.id = (select max(c.id))
Let's say, it's T.
So, your query now becomes:
SELECT u.thumbnail, u.id FROM users AS u
INNER JOIN
(
SELECT c.id, c.user_id FROM contestants AS c
WHERE u.id = c.users_id
AND c.id = (select max(c.id))
) AS T
WHERE u.thumbnail IS NOT NULL
But what you are trying to achieve, can actually be done in a neater way:
SELECT u.thumbnail, u.id, max(c.id),
FROM users as u
LEFT JOIN contestants as c
on u.id = c.user_id
WHERE u.thumbnail IS NOT NULL
Why make all the fuss when you have a better and neater approach at your disposal?
try this:
SELECT u.thumbnail, u.id
FROM users AS u
INNER JOIN
(
SELECT c.id, c.user_id FROM contestants AS c
WHERE u.id = c.users_id
AND c.id = (select max(c.id))
)A
WHERE u.thumbnail IS NOT NULL
i think this should be simple,
SELECT u.thumbnail, u.id
FROM users u
INNER JOIN contestants c
ON u.id = c.users_id
WHERE u.thumbnail IS NOT NULL
ORDER BY c.id DESC
LIMIT 1
This is very simple.
SELECT user.thumbnail, user.id
FROM users user
INNER JOIN contestants cont ON cont.id = cont.users_id
WHERE cont.thumbnail IS NOT NULL
ORDER BY user.id DESC
I've a very nice query that selects friends of the current user. user_id = 2 in the example. His friend is user_id = 4.
I want the same query to fetch the number of words user_id 2 has with selected friends. In this case they have word = love, and this is also word they both have, so I want in_common row to say = 1.
Is it possible without changing too much current query?
Should I start from scratch?
SQL FIDDLE
Assuming that both users would have an entry for 'love' in the words_en table then something like this maybe:-
SELECT b.name_surname,
b.avatar,
b.friend_words,
(b.friend_msg_id) AS friend_msg_id,
words_common.words_in_common,
COUNT(m.id) AS unread_msg
FROM
(
SELECT a.name_surname as name_surname,
a.avatar as avatar,
GROUP_CONCAT(DISTINCT w.word ORDER BY w.word ASC) AS friend_words,
(a.friend_id) AS friend_msg_id
FROM
(
SELECT f1.asked_user_id AS friend_id,
f1.created,
u.name_surname,
u.avatar
FROM friends AS f1
INNER JOIN friends AS f2
ON f1.asked_user_id = f2.asker_user_id
AND f1.asker_user_id = f2.asked_user_id
INNER JOIN users AS u ON f1.asked_user_id = u.id
WHERE f1.status = 1 AND f2.status = 1
AND f1.asker_user_id = 2
) a
LEFT JOIN connections c ON c.user_id = a.friend_id
AND c.invisible <> 1 AND c.deleted <> 1
LEFT JOIN words_en w ON c.word_id = w.id
GROUP BY 1
) b
LEFT JOIN messages m ON m.to_user_id = 2
AND m.from_user_id = b.friend_msg_id
AND m.seen = 0
LEFT OUTER JOIN
(
SELECT b.user_id AS friend_id, GROUP_CONCAT(a.word) AS words_in_common
FROM words_en a
INNER JOIN words_en b
ON a.word = b.word
WHERE a.user_id = 2
GROUP BY b.user_id
) words_common
ON b.friend_msg_id = words_common.friend_id
GROUP BY b.name_surname, b.avatar, b.friend_words, b.friend_msg_id
ORDER BY unread_msg DESC
EDIT - modification to use connections table to find common words:-
SELECT b.name_surname,
b.avatar,
b.friend_words,
(b.friend_msg_id) AS friend_msg_id,
words_common.words_in_common,
COUNT(m.id) AS unread_msg
FROM
(
SELECT a.name_surname as name_surname,
a.avatar as avatar,
GROUP_CONCAT(DISTINCT w.word ORDER BY w.word ASC) AS friend_words,
(a.friend_id) AS friend_msg_id
FROM
(
SELECT f1.asked_user_id AS friend_id,
f1.created,
u.name_surname,
u.avatar
FROM friends AS f1
INNER JOIN friends AS f2
ON f1.asked_user_id = f2.asker_user_id
AND f1.asker_user_id = f2.asked_user_id
INNER JOIN users AS u ON f1.asked_user_id = u.id
WHERE f1.status = 1 AND f2.status = 1
AND f1.asker_user_id = 2
) a
LEFT JOIN connections c ON c.user_id = a.friend_id
AND c.invisible <> 1 AND c.deleted <> 1
LEFT JOIN words_en w ON c.word_id = w.id
GROUP BY 1
) b
LEFT JOIN messages m ON m.to_user_id = 2
AND m.from_user_id = b.friend_msg_id
AND m.seen = 0
LEFT OUTER JOIN
(
SELECT b.user_id AS friend_id, GROUP_CONCAT(c.word) AS words_in_common
FROM connections a
INNER JOIN connections b
ON a.word_id = b.word_id
INNER JOIN words_en c
ON b.word_id = c.id
WHERE a.user_id = 2
GROUP BY b.user_id
) words_common
ON b.friend_msg_id = words_common.friend_id
GROUP BY b.name_surname, b.avatar, b.friend_words, b.friend_msg_id
ORDER BY unread_msg DESC