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
Related
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
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 want to count the occurrence of the same user id in two tables.
The jos_findme table has all the users in it. The other two have as well the column "user id".
But I want the overall count in the two tables. I tried this but it does not work?
SELECT
c.user_id, count(c.user_id) AS counter
FROM
jos_findme as c
LEFT JOIN
jos_findme_bestof as b ON b.user_id = c.user_id
LEFT JOIN
jos_findme_pair as p ON p.user_id = c.user_id
WHERE
c.user_id > 0
GROUP BY c.user_id
ORDER BY counter DESC
LIMIT 10
ALL tables have the column "user_id". I just want to count them in the tables "jos_findme_bestof" and "jos_findme_pair"
Correlated subqueries could be useful here:
SELECT c.user_id,
(SELECT Count(*)
FROM jos_findme_bestof b
WHERE b.user_id = c.user_id),
(SELECT Count(*)
FROM jos_findme_pair p
WHERE p.user_id = c.user_id)
FROM jos_findme c
Try this
SELECT c.user_id,
Users1 = (SELECT COUNT(*) FROM jos_findme_bestof b WHERE b.user_id = c.user_id),
Users2 = (SELECT COUNT(*) FROM jos_findme_pair p WHERE p.user_id = c.user_id),
TotalUser = (SELECT COUNT(*) FROM jos_findme_bestof b WHERE b.user_id = c.user_id)
+
(SELECT COUNT(*) FROM jos_findme_pair p WHERE p.user_id= c.user_id)
FROM
jos_findme c
Here,
Users1 will return all users from jos_findme_bestof
Users2 will return all users from jos_findme_pair
TotalUser will be count of both the tables
Hope it would helps you!
Thanks.
Try this:
SELECT c.user_id, (IFNULL(b.bCount, 0) + IFNULL(p.pCount, 0)) AS counter
FROM jos_findme AS c
LEFT JOIN (SELECT b.user_id, COUNT(1) bCount
FROM jos_findme_bestof b
GROUP BY b.user_id
) AS b ON b.user_id = c.user_id
LEFT JOIN (SELECT p.user_id, COUNT(1) pCount
FROM jos_findme_pair p
GROUP BY p.user_id
) AS p ON p.user_id = c.user_id
WHERE c.user_id > 0
GROUP BY c.user_id
ORDER BY counter DESC
LIMIT 10
I think you can do something like this:
SELECT AA.user_id, AA.Acounter + BB.Bcounter
from (SELECT a.user_id, count(a.user_id) AS Acounter
FROM jos_findme_bestof as a
GROUP BY a.user_id) as AA
Join
(SELECT b.user_id, count(b.user_id) AS Bcounter
FROM jos_findme_pair as b
GROUP BY b.user_id) as BB
on AA.user_id = BB.user_id
if you wants all the ids (meaning if there are id's in jos_findme_pair that are not in jos_findme_bestof) - use FULL OUTER JOIN
To get pending request for selected user I use:
SELECT f1.asker_user_id AS friend_id
FROM friends AS f1
LEFT JOIN friends AS f2
ON f1.asked_user_id = f2.asker_user_id
AND f1.asker_user_id = f2.asked_user_id
WHERE f1.status = 1 AND f2.status IS NULL
AND f1.asked_user_id = 2
http://www.sqlfiddle.com/#!2/0f7a0d5/65 It correctly returns user 3. VALUES (3,2,1)
But I'd like to get more data about this user 3.
I need name_surname and avatar from users table.
And all word_ids of this user from connections table, which in return would show word from words_en based on word_id.
Thanks allot!
p.s. I tried this:
SELECT a.name_surname,GROUP_CONCAT(Distinct w.word Order by w.word asc) AS words
FROM (
SELECT f1.asked_user_id AS friend_id,
f1.created,
u.name_surname,
u.avatar
FROM friends AS f1
LEFT JOIN friends AS f2 ON f1.asked_user_id = f2.asker_user_id
INNER JOIN users AS u ON f1.asked_user_id = u.id
AND f1.asker_user_id = f2.asked_user_id
WHERE f1.status = 1 AND f2.status IS NULL
AND f1.asker_user_id = 2
) a
LEFT JOIN connections c ON c.user_id = a.friend_id
LEFT JOIN words_en w ON c.word_id = w.id
GROUP BY 1;
Based on this question and your previous questions, i think you might be looking for something like this:
SELECT u.name_surname,
u.avatar,
GROUP_CONCAT(DISTINCT w.word Order by w.word asc) AS words
FROM users u
INNER JOIN
(
SELECT f1.asker_user_id AS friend_id
FROM friends AS f1
LEFT JOIN friends AS f2
ON f1.asked_user_id = f2.asker_user_id
AND f1.asker_user_id = f2.asked_user_id
WHERE f1.status = 1 AND f2.status IS NULL
AND f1.asked_user_id = 2
) a ON a.friend_id = u.id
LEFT JOIN connections c ON u.id = c.user_id
LEFT JOIN words_en w ON w.id = c.word_id
GROUP BY u.id;
sqlfiddle demo
HERE IS THE SQL Fiddle of the below query, which is what i think you are after.
SELECT users.name_surname, users.avatar,
GROUP_CONCAT(DISTINCT words_en.word Order by words_en.word asc) AS words
FROM
(
SELECT f1.asker_user_id AS friend_id
FROM friends AS f1
LEFT JOIN friends AS f2
ON f1.asked_user_id = f2.asker_user_id
AND f1.asker_user_id = f2.asked_user_id
WHERE f1.status = 1 AND f2.status IS NULL
AND f1.asked_user_id = 2
) AS MainQ
INNER JOIN users ON MainQ.friend_id = users.id
INNER JOIN connections ON users.id = connections.user_id
INNER JOIN words_en ON words_en.id = connections.word_id