MySQL move where clause inside subquery - mysql

I have written the following MySQL query. However, I need to move the FIND_IN_SET where clause inside the sub query which joins the actions table.
Is this possible? When I try and move that part inside the subquery it gives me the error, paths column does not exist.
select
users_roles.role_id,
ar.actions,
a.paths
from users_roles
join
(
select
action_id,
role_id,
group_concat(action_id SEPARATOR ',') as actions
from actions_roles
) as ar on ar.role_id = users_roles.role_id
join
(
select
id,
group_concat(path SEPARATOR ',') as paths
from actions
) as a on a.id = ar.action_id
where
users_roles.user_id = 1 and FIND_IN_SET('/admin', paths);

It is possible, try this:
select
users_roles.role_id,
ar.actions,
a.paths
from users_roles
join
(
select
action_id,
role_id,
group_concat(action_id SEPARATOR ',') as actions
from actions_roles
) as ar on ar.role_id = users_roles.role_id
join
(
select
id,
group_concat(path SEPARATOR ',') as paths
from actions
having FIND_IN_SET('/admin', group_concat(path SEPARATOR ',')) > 0
) as a on a.id = ar.action_id
where
users_roles.user_id = 1
Since the paths column you are passing to the function is actually the result of group_concat() function inside your sub-query, all you need to do is add a HAVING clause in the sub-query and change the alias of the column with the actual call of the function, which you also use to generate the data.
Why HAVING and not WHERE?
Because you're verifying the result of group_concat() which is an aggregate function. And the result of aggregate functions can be filtered only through a HAVING clause.

Related

How to get a concrete row from a subquery comparing values from the main query?

I need to get a concrete row from a subquery that returns multiple values from the value that gets the main query in which the sub is going to be called.
So this is my main query:
select ...
from xxxx cons
inner join ...
inner join ...
inner join ...
And I want to apply this subquery into that monster:
(SELECT con.cs_nombre, GROUP_CONCAT(DISTINCT cli_codigo SEPARATOR ' ')
from trcon con
INNER JOIN trcli clin on con.cs_nombre = clin.cli_nombre
group by con.cs_nombre)
This in order to get the group_concat row from the subquery in which the cs_nombre is the same as the one that gets the main query.
I think you can just use a correlated subquery:
SELECT . . .,
(SELECT GROUP_CONCAT(DISTINCT clin.cli_codigoCli SEPARATOR ' ')
FROM trcli clin
WHERE clin.cli_nombre= cons.cs_nombre
) as cli_codigo

group_concat result not work in IN condition

Is there any possible way to put result of group_concat in IN condition of SQL query.
Here in network master table i have comma separated fields in industryId column.
Like,
userId industryId
123 3831
123 2832,3832
123 3833
Example:
select group_concat(industryId order by cId SEPARATOR ',') from
network_master where userId = 123
and it gives me this type of output 3831,2832,3832,3833
I got this type of output using upper query,
userId industryId
123 3831,2832,3832,3833
and now i done this things,
select * from industry_master where industryId in (select
group_concat(industryId order by cId SEPARATOR ',') from
network_master where userId =123 group by userId);
In this query result, I got details output of industryId=3831 only. I did not get other Ids output.
I need all the industryId output in this query. How to i achieve this things in mysql.
Any help would be appreciated.
I have tried above case but not working on my side. I just edited above answer and removed > 0 then I can see your expected output.
Can you try below code?
select * from industry_master where find_in_set(industryId, (select group_concat(industryId order by cId SEPARATOR ',')
from network_master where userId = 123 group by userId));
you don't need group_concat and IN clause you can use a join
select i.*
from industry_master i
INNER JOIN network_master n on i.industryId = n.industryId
AND n.userId =123
group_concat return a string but you need values so using the string in IN clause don't work correctly.
or if can work only an a string you could trying using field_in_set > 0
select * from industry_master
where find_in_set(industryId, select group_concat(industryId order by cId SEPARATOR ',')
from network_master where userId =123 group by userId) ;
or

MySQL select query using 2 conditions

My following query shows results only if dcno is exists in dc_detail table
but what i actually need is even then if dcno is not exists in dc_detail table it should define dcno as 0 and select that results also
Thanks in advance
SELECT p.po_no as id, DATE_FORMAT(p.po_date, '%d-%m-%Y')as po_date, p.customer, p.cust_po as po_no,p.tot_ord_qty,
DATE_FORMAT(p.delivery_date, '%d-%m-%Y')as delivery_date,p.dc_status,p.inv_status,p.tot_dc_qty,p.tot_inv_qty,
GROUP_CONCAT(distinct d.dc_no SEPARATOR ', ') as dc FROM po_header p, dc_details d
where p.cust_po=d.cust_po
group by p.cust_po;
You should use left join to include headers that have no details. That will give you rows with nulls for the detail fields that don't exist.
To get the value 0 instead of null you can use coalesce function.
The relevant parts of the query are
SELECT COALESCE(d.dc_no, 0),...
FROM po_header p LEFT JOIN dc_detail d ON p.cust_po=d.cust_po
Coalesce function returns the first non null argument.

group concat from subquery very slow

Coming from here sql group_concat and subquery
I managed to "solve" de problem by doing this a "subquery":
SELECT
GROUP_CONCAT(name,',',results separator '#')
as finalresult
FROM
(
select t.name as name, group_concat(distinct r.idResult separator '-') as results
from threshold t
left join threshold_results r on r.idThreshold = t.idThreshold
group by t.idThreshold, t.name
) final
But it is too slow when there are many records, withouth the subquery the initial solution performs very well. Any ideas?
Thank you!
add index on r.idThreshold, t.name

Mysql Distinct function nested within other function in select

Is there a way we can use disctinct for below cd.date_id? It's getting concatenated but I would also like distinct function aswell so it's like GROUP_CONCAT( CAST( distinct(cd.date_id) AS CHAR ) ) As date_id but it does not seem to work...
SELECT b.bar_id, b.bar_name, b.bar_image, b.bar_lat, b.bar_lng, b.bar_address,
b.bar_phone, b.bus_web, b.bar_open_hours, c.coupon_id, c.coupon_text,
bc.coupon_start_time, bc.coupon_exp_time,
GROUP_CONCAT( CAST( cd.date_id AS CHAR ) ) As date_id,
d.calender_date, bc.bc_id, bc.priority As priority
FROM bars b
JOIN bars_coupons bc ON (bc.bar_id = b.bar_id)
JOIN coupons c ON (bc.coupon_id = c.coupon_id)
JOIN calendardates cd ON (cd.bc_id = bc.bc_id)
JOIN date d ON (d.date_id = cd.date_id)
GROUP BY cd.bc_id
DISTINCT inside there would not make any sense. What do you want to do here exactly? It seems you want only one row per distinct cd.date_id.
If that's the case just add cd.date_id to your GROUP BY clause at the end. Like this:
GROUP BY cd.bc_id, cd.date_id
And as you are using MySQL, you need not worry about using aggregate functions on all selected columns, if they would have the same value in all rows Grouped by the Group By clause, if not MySQL will just pick the first one
UPDATE
Looking at documentation for GROUP_CONCAT, you might be able to do it like this
GROUP_CONCAT( DISTINCT CAST(cd.date_id AS CHAR) ) As date_id