MySQL - Group BY GROUP_CONCAT - mysql

I have the following query:
SELECT
issue.`sequence` AS issue_sequence,
issue.`description` AS issue_description,
GROUP_CONCAT(DISTINCT(issue_category.`name`) SEPARATOR ', ') AS issue_category_name,
GROUP_CONCAT(DISTINCT(approach.`name`) SEPARATOR ', ') AS approach_name,
issue_approach.`issue_id` AS issue_approach_issue_id,
issue_approach.`approach_id` AS issue_approach_approach_id
FROM
`approach` approach
INNER JOIN `issue_approach` issue_approach ON approach.`id` = issue_approach.`approach_id`
INNER JOIN `issue` issue ON issue_approach.`issue_id` = issue.`id`
INNER JOIN `project` project ON issue.`project` = project.`id`
INNER JOIN `tenant` tenant ON project.`tenant_id` = tenant.`id`
INNER JOIN `issue_category` issue_category ON project.`id` = issue_category.`project`
INNER JOIN `user` user ON tenant.`id` = user.`tenant_id`
WHERE user.id = 1 AND project.id = 1
GROUP BY issue_category_name
ORDER BY issue_category.`name`, issue.`sequence`
I am having a problem with this line:
GROUP BY issue_category_name
Apparently, MySQL can't seem to Group by the alias for by GROUP_CONCAT result.
I am not really an expert with SQL, but is there a way I can group using the result of GROUP_CONCAT?
Sample data;
Categories: Network, Servers
Issue Id: 1
Description: Some description
Approaches: Some approaches to resolve the issue.
Basically, an issue can belong to one or many categories. I am concatenating categories for each issue. What i want to do is group the results by the result of concatenation of categories. So for example group issues whose categories are Network,Servers.
Thanks.

Im not a MySQL user, but change your group by to
Group By GROUP_CONCAT(DISTINCT(issue_category.`name`) SEPARATOR ', ')

With reference to SQL EXECUTION ORDER, the reason why this will not work is because the select statement is the last statement to be executed so that sql engine will not be knowing your column alias while grouping the records as GROUP BY occurs before SELECT. So that as Charles Bretana's answer suggests, put
Group By GROUP_CONCAT(DISTINCT(issue_category.`name`) SEPARATOR ', ')
in your group by clause. It will work fine then.
Hope this helps you.

Related

MySQL - Operand should contain 1 column(s)

While working on a system I'm creating, I attempted to use the following query in my project:
SELECT
topics.id,
topics.name,
topics.post_count,
topics.view_count,
COUNT( posts.solved_post ) AS solved_post,
(SELECT users.username AS posted_by,
users.id AS posted_by_id
FROM users
WHERE users.id = posts.posted_by)
FROM topics
LEFT OUTER JOIN posts ON posts.topic_id = topics.id
WHERE topics.cat_id = :cat
GROUP BY topics.id
":cat" is bound by my PHP code as I'm using PDO. 2 is a valid value for ":cat".
That query though gives me an error: "#1241 - Operand should contain 1 column(s)"
What stumps me is that I would think that this query would work no problem. Selecting columns, then selecting two more from another table, and continuing on from there. I just can't figure out what the problem is.
Is there a simple fix to this, or another way to write my query?
Your subquery is selecting two columns, while you are using it to project one column (as part of the outer SELECT clause). You can only select one column from such a query in this context.
Consider joining to the users table instead; this will give you more flexibility when selecting what columns you want from users.
SELECT
topics.id,
topics.name,
topics.post_count,
topics.view_count,
COUNT( posts.solved_post ) AS solved_post,
users.username AS posted_by,
users.id AS posted_by_id
FROM topics
LEFT OUTER JOIN posts ON posts.topic_id = topics.id
LEFT OUTER JOIN users ON users.id = posts.posted_by
WHERE topics.cat_id = :cat
GROUP BY topics.id
In my case, the problem was that I sorrounded my columns selection with parenthesis by mistake:
SELECT (p.column1, p.column2, p.column3) FROM table1 p WHERE p.column1 = 1;
And has to be:
SELECT p.column1, p.column2, p.column3 FROM table1 p WHERE p.column1 = 1;
Sounds silly, but it was causing this error and it took some time to figure it out.
This error can also occur if you accidentally use commas instead of AND in the ON clause of a JOIN:
JOIN joined_table ON (joined_table.column = table.column, joined_table.column2 = table.column2)
^
should be AND, not a comma
This error can also occur if you accidentally use = instead of IN in the WHERE clause:
FOR EXAMPLE:
WHERE product_id = (1,2,3);
COUNT( posts.solved_post ) AS solved_post,
(SELECT users.username AS posted_by,
users.id AS posted_by_id
FROM users
WHERE users.id = posts.posted_by)
Well, you can’t get multiple columns from one subquery like that. Luckily, the second column is already posts.posted_by! So:
SELECT
topics.id,
topics.name,
topics.post_count,
topics.view_count,
posts.posted_by
COUNT( posts.solved_post ) AS solved_post,
(SELECT users.username AS posted_by_username
FROM users
WHERE users.id = posts.posted_by)
...
I got this error while executing a MySQL script in an Intellij console, because of adding brackets in the wrong place:
WRONG:
SELECT user.id
FROM user
WHERE id IN (:ids); # Do not put brackets around list argument
RIGHT:
SELECT user.id
FROM user
WHERE id IN :ids; # No brackets is correct
This error can also occur if you accidentally miss if function name.
for example:
set v_filter_value = 100;
select
f_id,
f_sale_value
from
t_seller
where
f_id = 5
and (v_filter_value <> 0, f_sale_value = v_filter_value, true);
Got this problem when I missed putting if in the if function!
Another place this error can happen in is assigning a value that has a comma outside of a string. For example:
SET totalvalue = (IFNULL(i.subtotal,0) + IFNULL(i.tax,0),0)
(SELECT users.username AS posted_by,
users.id AS posted_by_id
FROM users
WHERE users.id = posts.posted_by)
Here you using sub-query but this sub-query must return only one column.
Separate it otherwise it will shows error.
I also have the same issue in making a company database.
this is the code
SELECT FNAME,DNO FROM EMP
WHERE SALARY IN (SELECT MAX(SALARY), DNO
FROM EMP GROUP BY DNO);

SQL: Display multiple record values in one field from a subquery

I have an SQL LIKE:
SELECT S.*,
(SELECT I.NAME FROM institution I, inst_map IM
WHERE IM.STUDENT = S.ID AND IM.INSTITUTION = I.ID) as INSTITUTIONS
FROM student S
In this case it is possible for my subquery to return multiple records (I will get an error: Subquery returns more than 1 row).
How to show those multiple values from my subquery in one field (in my case INSTITUTIONS ) separated by commas?
All ideas are welcome.
Try this query -
SELECT s.*, GROUP_CONCAT(t.NAME) INSTITUTIONS FROM student s
LEFT JOIN (SELECT * FROM institution i
JOIN inst_map im
ON im.INSTITUTION = i.ID
) t
ON s.ID = t.STUDENT
GROUP BY s.ID
The GROUP_CONCAT function will help you to get values separated by commas.
DECLARE #List VARCHAR(5000)
SELECT #List = COALESCE(#List + ', ' + Display, Display)
FROM TestTable
Order By Display
query is taken from following link, and the article explain the query perfectly, I hope it works
http://www.mitchelsellers.com/blogs/articletype/articleview/articleid/289/creating-comma-separated-list-in-sql.aspx
P.S Its for SQL Server, i guess

Slow subquery in MySQL

im trying to generate a report using CodeIgniter and Datatables.net .
Now i'm trying to the amount of closed jobs (its a human resources system). I used to query all jobs and in PHP do a foreach and then doing the calcs.
Because im want to use all the features of Datatables (sorting specifically) im trying to do all the calcs in mySQL.
The problem is: the second subquery is very very very slow.
SELECT
jobs.jobs_id, clients.nome_fantasia, concat_ws(' ', user_profiles.first_name, user_profiles.last_name) as fullname,
jobs.titulo_vaga, jobs.qtd_vagas, company.name as nome_company, jobs_status.name as status_name, DATEDIFF(NOW(), jobs.data_abertura) as date_idade,
(select count(job_cv.jobs_id) from job_cv where job_cv.jobs_id = jobs.jobs_id) as qtd_int,
(select count(distinct job_cv.user_id) from job_cv_history join job_cv on job_cv.job_cv_id = job_cv_history.job_cv_id where job_cv_history.status = '11' and job_cv.jobs_id = jobs.jobs_id ) as fechadas
FROM (jobs)
JOIN clients ON lients.clients_id=jobs.clients_idJOIN user_profiles ON jobs.consultor_id=user_profiles.user_id
JOIN jobs_status ON jobs.status=jobs_status.jobs_status_id
JOIN company ON jobs.company_id=company.company_id
LIMIT 50
Some one can help me? I can provide more information if its needed.
UPDATE
The idea to use JOIN instead SELECT work with the first subquery but with the second one not, there a way to pass a 'variable' to use inside the subquery? Like the current jobs_id?
UPDATE AGAIN
This line works fine by itself. But inside the subquery take about a minute with worng values
SELECT job_cv.jobs_id,count(distinct job_cv.user_id) AS fechadas
FROM job_cv_history
JOIN job_cv
ON job_cv.job_cv_id = job_cv_history.job_cv_id
WHERE job_cv_history.status = '11'
GROUP BY job_cv.jobs_id
It is not subquery that is slow. It's the fact, that you're executing these subqueries for each row returned from outer query. Move these to joins instead, and you should observe increase in performance.
SELECT
jobs.jobs_id, clients.nome_fantasia, concat_ws(' ', user_profiles.first_name, user_profiles.last_name) as fullname,
jobs.titulo_vaga, jobs.qtd_vagas, company.name as nome_company, jobs_status.name as status_name, DATEDIFF(NOW(), jobs.data_abertura) as date_idade,
qtd.qtd_int,
fechadas.fechadas
FROM (jobs)
JOIN clients ON lients.clients_id=jobs.clients_idJOIN user_profiles ON jobs.consultor_id=user_profiles.user_id
JOIN jobs_status ON jobs.status=jobs_status.jobs_status_id
JOIN company ON jobs.company_id=company.company_id
JOIN (
SELECT jobs_id, count(jobs_id) AS qtd_int FROM job_cv GROUP BY jobs_id
) AS qtd ON qtd.jobs_id = jobs.jobs_id
JOIN (
SELECT job_cv.user_id, count(distinct job_cv.user_id) AS fechadas
FROM job_cv_history
JOIN job_cv
ON job_cv.job_cv_id = job_cv_history.job_cv_id
WHERE job_cv_history.status = '11'
GROUP BY job_cv.user_id
) AS fechadas ON job_cv.jobs_id = jobs.jobs_id
LIMIT 50
You may try to create these indexes:
ALTER TABLE `job_cv` ADD INDEX `job_cv_cindex` (`job_cv_id` ASC, `jobs_id` ASC, `user_id` ASC);
ALTER TABLE `job_cv_history` ADD INDEX `job_cv_history_cindex` (`job_cv_id` ASC, `status` ASC);
use Joins instead of sub queries. It significantly improves the performance in MySql.
try to use Left join on your case and see if performance improves or not

MySQL: UPDATE with a JOIN and a GROUP_CONCAT

Is this possible?
I have 2 tables, Customers and Orders. Now I want to fill a column in Customers with all order id's of that customer (comma separated).
I tried something like this, but it doesnt work:
UPDATE customers AS c
LEFT JOIN orders AS o ON o.customerid=c.customerid
SET c.orders = GROUP_CONCAT(DISTINCT o.orderid)
I get 'Invalid use of group function'.
PS. I know it's better to always dynamically get the GROUP_CONCAT values in a SELECT/JOIN, but I'm just wondering if I can fill this column in some way.
You will need to add an order by in the group_concat as shown in the example below
Note: group_concat(version ORDER BY version SEPARATOR ',')
UPDATE
items i,
(SELECT pduid, group_concat(version ORDER BY version SEPARATOR ',') AS 'versions'
from items GROUP BY pduid) AS version_lookup
SET i.versions = version_lookup.versions
WHERE version_lookup.pduid = i.pduid
None of the given answers here were working for me, possibly because my case was more complicated (I needed more than one join), so I used Dennis' solution but split it into a temporary table:
CREATE TEMPORARY TABLE version_lookup
SELECT pduid, group_concat(version ORDER BY version SEPARATOR ',') AS 'versions'
from items GROUP BY pduid;
UPDATE
items i, version_lookup
SET i.versions = version_lookup.versions
WHERE version_lookup.pduid = i.pduid;
Basically you should not use the GROUP_CONCAT function in this manner, that's not the right way of making your work done.
In this scenario you can use nested queries approach instead of trying with JOINs as I specified below, try this query, hopefully this should do your work correctly.
UPDATE customers AS c
SET c.orders =
(SELECT GROUP_CONCAT(DISTINCT o.orderid)
FROM orders AS o
WHERE o.customerid = c.customerid
GROUP BY o.customerid);
Try this query once and then let me know if you are facing any more issues.
Siva
You forget to tell the GROUP BY clause.
UPDATE customers AS c
LEFT JOIN orders AS o ON o.customerid=c.customerid
SET c.orders = GROUP_CONCAT(DISTINCT o.orderid)
GROUP BY o.customerid

How to use mySQL count using joins?

I am having following database schema, I want to fetch name of all categories with no of quotes related to that category . The query that i wrote giving me one row only can u please tell me the resource efficient query.
SELECT SC.Name, Count(*) AS Quotes
FROM status_categories AS SC
INNER JOIN status_quotes AS SQ ON SC._id = SQ._category_id
GROUP BY SC.Name
SELECT status_categories.NAME, COUNT(status_quotes.category_id)
FROM status_categories JOIN status_quotes ON status_categories._id = status_quotes.category_id
GROUP BY status_categories._id;
Try the following:
SELECT `c`.`name`, COUNT(*) AS `Number of quotes`
FROM `status_categories` AS `c`
INNER JOIN `status_quotes` AS `q`
ON `q`.`category_id` = `c`.`_id`
GROUP BY `c`.`_id`;
EDIT
Feel free to leave out the ` character. But that is the safe way of doing it, even though it looks a bit nasty.