GROUP_CONCAT too slow - php

Hello I added GROUP_CONCAT function to my query and that function killed my query :/.
My query is :
SELECT u.username,a.user_id,a.id,a.text,a.lang as fromLang,b.lang as toLang,GROUP_CONCAT(DISTINCT b.id) AS translation_ids FROM sentence as a
INNER JOIN sentence_relationship as sr ON
(sr.sentence_id = a.id)
INNER JOIN sentence as b ON
(b.id = sr.translation_id AND a.id = sr.sentence_id)
INNER JOIN users as u ON
(u.id = a.user_id) GROUP BY a.id LIMIT 10;
What is wrong with that query ?

This is your query (somewhat formatted):
SELECT u.username, a.user_id, a.id,a.text,a.lang as fromLang, b.lang as toLang,
GROUP_CONCAT(DISTINCT b.id) AS translation_ids
FROM sentence a INNER JOIN
sentence_relationship sr
ON sr.sentence_id = a.id INNER JOIN
sentence b
ON b.id = sr.translation_id AND a.id = sr.sentence_id INNER JOIN
users as u
ON u.id = a.user_id
GROUP BY a.id
LIMIT 10;
It is unclear from your question whether the group_concat() was added with the group by. That could slow things down.
The limit 10 is taking the first 10 a.ids that match (the group by does an implicit ordering). If you do this with a subquery, it will probably speed up the query:
SELECT u.username, a.user_id, a.id,a.text,a.lang as fromLang, b.lang as toLang,
GROUP_CONCAT(DISTINCT b.id) AS translation_ids
FROM (select s.*
from sentence s
order by a.id
limit 10
) a INNER JOIN
sentence_relationship sr
ON sr.sentence_id = a.id INNER JOIN
sentence b
ON b.id = sr.translation_id AND a.id = sr.sentence_id INNER JOIN
users as u
ON u.id = a.user_id
GROUP BY a.id;
This assumes that all the joins do work and match records. If the joins are used for filtering, then you may get fewer than 10 rows back.

Related

I'm not able to convert the Mysql query into laravel query builder

I'm struggling to convert this below MySQL query into laravel query builder. It has a lot of joins and subqueries inside. Can someone please help me?
MYSQL query:
SELECT a.id , b.*, a.agent_id, td.contacts, td.addresses
FROM teams a
left join team_details as td on td.team_id = a.id
LEFT OUTER JOIN
(
SELECT m.id, m.due_date, t.team_id, m.department, m.assigned_to , cm.title, u.name
FROM (
SELECT team_id, MAX(due_date) AS due_date
FROM campaign_activities where task_status=false and due_date is not null
GROUP BY team_id
) t JOIN campaign_activities m ON m.team_id = t.team_id AND t.due_date = m.due_date
left join campaign_activity_masters cm on cm.id = m.camp_activity_id
left join users u on u.id = m.assigned_to
) b ON a.id = b.team_id
order by a.id
I'm trying something like below but got stuck with LEFT OUTER JOIN as it has sub query inside :).
DB::table('teams as a')
->leftjoin('team_details as td', 'td.team_id','=','a.id')
->select('a.id', 'b.*', 'a.agent_id','td.contacts','td.addresses')
->leftouterjoin(DB::select(DB::raw('SELECT m.id, m.due_date, t.team_id, m.department, m.assigned_to , cm.title, u.name
FROM (
SELECT team_id, MAX(due_date) AS due_date
FROM campaign_activities where task_status=false and due_date is not null
GROUP BY team_id
) t JOIN campaign_activities m ON m.team_id = t.team_id AND t.due_date = m.due_date
left join campaign_activity_masters cm on cm.id = m.camp_activity_id
left join users u on u.id = m.assigned_to')))
->get();
Any suggestions, please? I want to apply paginate function paginate() instead of get() for this query builder.
I think you should try.
$cards = DB::select("SELECT a.id , b.*, a.agent_id, td.contacts, td.addresses
FROM teams a
left join team_details as td on td.team_id = a.id
LEFT OUTER JOIN
(
SELECT m.id, m.due_date, t.team_id, m.department, m.assigned_to , cm.title, u.name
FROM (
SELECT team_id, MAX(due_date) AS due_date
FROM campaign_activities where task_status=false and due_date is not null
GROUP BY team_id
) t JOIN campaign_activities m ON m.team_id = t.team_id AND t.due_date = m.due_date
left join campaign_activity_masters cm on cm.id = m.camp_activity_id
left join users u on u.id = m.assigned_to
) b ON a.id = b.team_id
order by a.id");
Hope it help you.

Need distinct value based on id when we JOIN 4 tables in PHP/MYSQL

Here is my SQL query which joins 4 tables and it works correctly.
SELECT pl.lms_id, u.id, REPLACE(trim(u.`url`), 'www.', '') AS url, trim(u.`name`) as name, p.date_removed, p.status, p.ignore_status FROM `adl_seo_status` p INNER JOIN `adl_user_profiles` u on p.profile_id = u.id INNER JOIN adl_tw_profile_acc_type ac on p.profile_id = ac.profile_id LEFT JOIN `adl_lms_prof_list` pl on u.id = pl.profile_id WHERE u.`vpg_id`='2' AND u.`status` = 'Y' and ac.acc_type_id = '2' ORDER BY u.`url` ASC, p.id DESC
I am facing an issue that, the table adl_seo_status has multiple entries for a single profile_id. So, that accounts are repeating in my listing. I want that account as a single row which means the distinct value of accounts based on profile_id.
You need to use group by, for example:
SELECT
pl.lms_id,
u.id,
REPLACE(trim(u.`url`), 'www.', '') AS url,
trim(u.`name`) AS name,
p.date_removed,
p.status,
p.ignore_status
FROM `adl_seo_status` p INNER JOIN `adl_user_profiles` u ON p.profile_id = u.id
INNER JOIN adl_tw_profile_acc_type ac ON p.profile_id = ac.profile_id
LEFT JOIN `adl_lms_prof_list` pl ON u.id = pl.profile_id
WHERE u.`vpg_id` = '2' AND u.`status` = 'Y' AND ac.acc_type_id = '2'
ORDER BY u.`url` ASC, p.id DESC GROUP BY p.profile_id;

select count of rows from 2 tables and merge into one row (mysqli)

i create a web app like facebook by php and mysqli
in my app i have a table for posts , one table for likes , and one table for comments
i want to get the number of comments and likes of each post in one row with his post_id!!!
i try some querys likes this :
select `tblpost`.`post_id`, COALESCE(TCOMM.`comment_num`,0) as `c_num`, COALESCE(TLIKE.`like_num`,0) as `l_num`
from
(select `tblpost`.`post_id`, count(*) as `like_num` from `tblpost` join `tbllikes` on `tbllikes`.`post_id` = `tblpost`.`post_id` group by `tblpost`.`post_id`
) TLIKE
inner join
(select `tblpost`.`post_id`, count(*) as `comment_num` from `tblpost` join `tblcomments` on `tblcomments`.`post_id` = `tblpost`.`post_id` group by `tblpost`.`post_id`) TCOMM
on
TCOMM.`post_id` = TLIKE.`post_id`
but i don't know what's my problem
You can do count distincts with two left joins.
Something like this would work if there are fields like_id and comment_id in the tables tbllikes and tblcomments
SELECT
tblpost.post_id AS post_id,
COUNT(DISTINCT tbllikes.like_id) AS likes,
COUNT(DiSTINCT tblcomments.comment_id) AS comments
FROM tblpost
LEFT JOIN tbllikes ON tbllikes.post_id = tblpost.post_id
LEFT JOIN tblcomments on tblcomments.post_id = tblpost.post_id
GROUP BY tblpost.post_id
First, I think you can greatly simplify your query:
select l.post_id,
COALESCE(c.comment_num, 0) as c_num, COALESCE(l.like_num, 0) as l_num
from (select l.post_id, count(*) as like_num
from tbllikes l
group by l.post_id
) l inner join
(select c.post_id, count(*) as comment_num
from tblcomments c
group by c.post_id
) c
on l.post_id = c.post_id;
This will only get you posts that have both likes and comments. To get what you want, use a left join:
select p.post_id,
COALESCE(c.comment_num, 0) as c_num, COALESCE(l.like_num, 0) as l_num
from tblpost p left join
(select l.post_id, count(*) as like_num
from tbllikes l
group by l.post_id
) l
on l.post_id = p.post_id left join
(select c.post_id, count(*) as comment_num
from tblcomments c
group by c.post_id
) c
on c.post_id = p.post_id;

MySQL query to order results by number of votes in another table for the specifc result/row

Okay, so I have a query below I am trying to get to work.
Basically everything works up until the inner join of the 'votes' table. What I am trying to do is order the results of this query in accordance with the number of votes each content row has in another table called votes. I know I'm not too far off from what I need to do!
Thanks in advance!!
mysql_query("
SELECT content.id, content.type, content.title, content.url, users.username
FROM content
INNER JOIN users ON content.uploaderuid = users.id
INNER JOIN votes ON votes.id = content.id
WHERE (content.type = 'pic')
ORDER BY COUNT(votes.id) DESC");
Try doing:
SELECT content.id, content.type, content.title, content.url, users.username
FROM content
INNER JOIN users ON content.uploaderuid = users.id
INNER JOIN (
SELECT id,COUNT(*) as voteCount
FROM votes
GROUP BY id
) v ON v.id = content.id
WHERE (content.type = 'pic')
ORDER BY v.voteCount DESC
When you do an INNER JOIN with votes table directly, if you have multiple occurrences of the same id, you will get a lot more rows than before you did the JOIN.
If you are only interested in the number of votes for each id, by doing a JOIN with a subquery that calculates the count of votes for each id, will leave your previous query results as they were, and lets you use the voteCount to order by it.
You could try this:
SELECT c.id, c.type, c.title, c.url, u.username, COUNT(v.id) votes
FROM content c
INNER JOIN users u ON c.uploaderuid = u.id
INNER JOIN votes v ON v.id = c.id
WHERE c.type = 'pic'
GROUP BY c.id, c.type, c.title, c.url, u.username
ORDER BY votes DESC
Here is the SQL Fiddle that demonstrates the below query:
SELECT c.id, c.type, c.title, c.url, u.username, COUNT(v.id)
FROM content AS c
INNER JOIN users AS u ON c.uploaderuid = u.id
INNER JOIN votes AS v ON v.id = c.id
WHERE c.type = 'pic'
GROUP BY c.id, c.type, c.title, c.url, u.username
ORDER BY COUNT(v.id) DESC

How to INNER JOIN more than two categories?

I'm a little confused in here and need some help...
the situation is I've made three tables(fr_Leagues, fr_nations and fr_confeds), all i want to do is add a league which shows the name of the categories not the i.d with pagination. Here is the code:
NOW FIXED!
"SELECT
a.id as confed_id,
a.fr_short_name as confed_name,
b.id as nation_id,
b.fr_name as nation_name,
c.id as league_id,
c.fr_name as league_name"
." FROM fr_confeds as a
INNER JOIN fr_nations as b ON a.id = b.confed_id
INNER JOIN fr_leagues as c ON b.id = c.nation_id"
." LIMIT $paginate->start, $paginate->limit"
You are missing on how to link the different tables together. On each INNER JOIN, you need to have it:
INNER JOIN fr_nations ON a.<someColumn> = b.<anotherColumn> INNER JOIN fr_leagues ON a.<someColumn> = b.<anotherColumn>
USE THIS QUERY
SELECT * FROM fr_confeds as A
INNER JOIN fr_nations as B ON A.id = B.confed_id
INNER JOIN fr_leagues as C ON B.confed_id = C.league_id
LIMIT $paginate->start, $paginate->limit

Categories