sql string can't get right - mysql

I'm trying to get some data from my db.
It kinda looks like this
GROUPS
groups_id, groups_name, groups_description, groups_active, groups_hash, groups_entry_date, user_id, groups_email, groups_sms
CUSTOMERS_GROUPS
customers_hash, groups_hash
CUSTOMERS
customers_id, customers_first_name, customers_surname, customers_telephone, customers_email, customers_telephone_active, customers_email_active, client_type, customers_hash, customers_entry_date
I want customers.groups_hash and groups.groups_name in a concat form. Here is my attempt ...
SELECT * , GROUP_CONCAT( DISTINCT customers_groups.groups_hash
SEPARATOR '/' ) , GROUP_CONCAT( groups.groups_name
SEPARATOR '/' )
FROM customers
INNER JOIN customers_groups ON ( customers.customers_hash = customers_groups.customers_hash )
LEFT JOIN groups ON ( customers_groups.customers_hash = groups.groups_hash )
WHERE groups.groups_active ='1' GROUP BY customers.customers_entry_date
but it gives me back a zero set ...

The problem is your where clause. It must be part of the on clause:
SELECT * , GROUP_CONCAT( DISTINCT customers_groups.groups_hash
SEPARATOR '/' ) , GROUP_CONCAT( groups.groups_name
SEPARATOR '/' )
FROM customers
INNER JOIN customers_groups ON ( customers.customers_hash = customers_groups.customers_hash )
LEFT JOIN groups ON ( customers_groups.customers_hash = groups.groups_hash ) AND groups.groups_active ='1'
GROUP BY customers.customers_entry_date

The problem is here:
LEFT JOIN groups ON ( customers_groups.customers_hash = groups.groups_hash )
which should probably be
LEFT JOIN groups ON ( customers_groups.groups_hash = groups.groups_hash )
(While it remains unclear what the hashes actually represent and why there is no bridge table linking the tables' IDs instead. I've asked that question in the comment section to your request.)

Related

mySQL Exclude entire result if GROUP_CONCAT returns NULL

If this is a dupe, I apologize. I couldn't find it.
I have this convoluted query that hits 3 tables, and I need to figure out how to exclude an entire result if the GROUP_CONCAT as shows returns NULL (which it does often). To clarify, if shows comes up NULL, then I don't want any of the profile data for that result either. I want the entire row skipped.
SELECT
`profiles`.*,
IF( `profiles`.`profile_id` IN(
SELECT DISTINCT (`badges`.`profile_id`)
FROM `badges`
), TRUE, FALSE ) AS `has_registrations`,
(SELECT
GROUP_CONCAT( DISTINCT `shows`.`show_name` SEPARATOR '<br>' )
FROM `shows`
LEFT JOIN `badges` ON `badges`.`show_id` = `shows`.`show_id`
WHERE
`badges`.`profile_id` = `profiles`.`profile_id`
AND `shows`.`end_date` >= CURDATE()
) AS `shows`
FROM `profiles`
Also accepting input on speed/elegance of the overall query.
Probably there is a more efficient way to do this but I think a simple where clause will do the trick.
SELECT
`profiles`.*,
IF( `profiles`.`profile_id` IN(
SELECT DISTINCT (`badges`.`profile_id`)
FROM `badges`
), TRUE, FALSE ) AS `has_registrations`,
(SELECT
GROUP_CONCAT( DISTINCT `shows`.`show_name` SEPARATOR '<br>' )
FROM `shows`
LEFT JOIN `badges` ON `badges`.`show_id` = `shows`.`show_id`
WHERE
`badges`.`profile_id` = `profiles`.`profile_id`
AND `shows`.`end_date` >= CURDATE()
) AS `shows`
FROM `profiles`
where `shows` IS NOT NULL
You could add a having clause:
SELECT
`profiles`.*,
IF( `profiles`.`profile_id` IN(
SELECT DISTINCT (`badges`.`profile_id`)
FROM `badges`
), TRUE, FALSE ) AS `has_registrations`,
(SELECT
GROUP_CONCAT( DISTINCT `shows`.`show_name` SEPARATOR '<br>' )
FROM `shows`
LEFT JOIN `badges` ON `badges`.`show_id` = `shows`.`show_id`
WHERE
`badges`.`profile_id` = `profiles`.`profile_id`
AND `shows`.`end_date` >= CURDATE()
) AS `shows`
FROM `profiles`
having shows is not null
If i understand questions correctly, you don't need null values. Perhaps the null value occurs due use of left join why don't you try with inner join their will be no null values.

GROUP_CONCAT not working as expected

I have a many to many relationship. Projects table, projects_users table, and users table. I am trying to return a listing of projects, with its associated users. Here is the query I'm using, which works, but only shows a single user, when I know there should be more:
SELECT
projects.id,
`projects`.`project_name`,
( GROUP_CONCAT(DISTINCT `users`.`name` separator ', ' ) ) AS staff,
FROM `projects`
INNER JOIN `projects_users` ON (`projects_users`.`project_id` = `projects`.`id` )
INNER JOIN `users` ON (`users`.`id` = `projects_users`.`user_id` )
GROUP BY projects.id, `projects_users`.`user_id`
HAVING (`projects_users`.`user_id` = 8)
There are several users associated with each project and I would expect to return something like "User 1, User 2, User 3". Instead, I only get "User 1."
Since you need to aggregate the users per project, you should group according to the user_id:
SELECT
projects.id,
`projects`.`project_name`,
( GROUP_CONCAT(DISTINCT `users`.`name` separator ', ' ) ) AS staff
FROM projects -- was missing in the OP
INNER JOIN `projects_users` ON (`projects_users`.`project_id` = `projects`.`id` )
INNER JOIN `users` ON (`users`.`id` = `projects_users`.`user_id` )
GROUP BY projects.id -- Group by fixed here
HAVING (`projects_users`.`user_id` = 8)

Mysql Subquery Work Slowly

I use view has subquery and concat in mysql. Normally, query works rapidly, but if query has subquery works very slowly.
This code is running quickly (approximate 1 seconds)
CREATE OR REPLACE VIEW ilceler AS (
SELECT I.id, I.modulid, I.id as icerikidsi,
MAX(IF(D.alanid=2,D.textkisa,NULL)) AS ilceadi,
MAX(IF(D.alanid=2,D.id,NULL)) AS ilceadi_i,
I.seo_description,
I.seo_h1,
I.seo_h2,
I.seo_h3,
I.seo_h4,
I.seo_imgalt,
I.seo_imgtitle,
I.seo_keywords,
I.seo_pagetitle,
I.seo_url,
I.seo_urltitle
FROM datalar as D LEFT JOIN icerikler as I ON D.icerikid=I.id WHERE D.modulid='3' GROUP BY D.icerikid ORDER BY sehiradi asc )
But this code is working very very slowly (approximate 20 seconds)
CREATE OR REPLACE VIEW ilceler AS (
SELECT I.id, I.modulid, I.id as icerikidsi,
MAX(IF(D.alanid=2,D.textkisa,NULL)) AS ilceadi,
MAX(IF(D.alanid=2,D.id,NULL)) AS ilceadi_i,
( SELECT CONVERT ( GROUP_CONCAT(D2.id SEPARATOR ' ₋ ' ) USING UTF8 )FROM datalar as D1
LEFT JOIN datalar as D2 ON D1.iliskialanid=D2.id WHERE D1.modulid='3' AND D1.alanid='3' AND D1.icerikid=icerikidsi ) as sehiradi_a ,
( SELECT GROUP_CONCAT(iliskiid SEPARATOR ' ₋ ') FROM datalar WHERE alanid='3' AND modulid='3' AND icerikid=icerikidsi ) as sehiradi_i,
( SELECT GROUP_CONCAT(D2.textkisa SEPARATOR ' ₋ ' ) FROM datalar as D1 LEFT JOIN datalar as D2 ON D1.iliskialanid=D2.id
WHERE D1.modulid='3' AND D1.alanid='3' AND D1.icerikid=icerikidsi ) as sehiradi ,
I.seo_description,
I.seo_h1,
I.seo_h2,
I.seo_h3,
I.seo_h4,
I.seo_imgalt,
I.seo_imgtitle,
I.seo_keywords,
I.seo_pagetitle,
I.seo_url,
I.seo_urltitle
FROM datalar as D LEFT JOIN icerikler as I ON D.icerikid=I.id WHERE D.modulid='3' GROUP BY D.icerikid ORDER BY sehiradi asc )
Why? Where do I make mistake?
I am waiting for your help.
Your sub queries rely on the values of the select, hence each of those 3 sub queries needs to be performed for each returned row. With a small number of rows this isn't an issue but with lots of rows this can rapidly add up.
Normal solution is to join against the sub query (hence it is done once for all rows and you just join the results).
For example:-
SELECT I.id,
I.modulid,
I.id as icerikidsi,
MAX(IF(D.alanid=2,D.textkisa,NULL)) AS ilceadi,
MAX(IF(D.alanid=2,D.id,NULL)) AS ilceadi_i,
sub1.sehiradi_a ,
sub2.sehiradi_i,
sub1.sehiradi ,
I.seo_description,
I.seo_h1,
I.seo_h2,
I.seo_h3,
I.seo_h4,
I.seo_imgalt,
I.seo_imgtitle,
I.seo_keywords,
I.seo_pagetitle,
I.seo_url,
I.seo_urltitle
FROM datalar as D
LEFT JOIN icerikler as I ON D.icerikid=I.id
LEFT OUTER JOIN
(
SELECT D1.icerikid, CONVERT ( GROUP_CONCAT(D2.id SEPARATOR ' ₋ ' ) USING UTF8 ) AS sehiradi_a, GROUP_CONCAT(D2.textkisa SEPARATOR ' ₋ ' ) AS sehiradi
FROM datalar as D1
LEFT JOIN datalar as D2 ON D1.iliskialanid=D2.id
WHERE D1.modulid='3'
AND D1.alanid='3'
GROUP BY D1.icerikid
) sub1
ON sub1.icerikid = I.id
LEFT OUTER JOIN
(
SELECT icerikid, GROUP_CONCAT(iliskiid SEPARATOR ' ₋ ') AS sehiradi_i
FROM datalar
WHERE alanid='3'
AND modulid='3'
GROUP BY icerikid
) sub2
ON sub2.icerikid = I.id
WHERE D.modulid='3'
GROUP BY D.icerikid
ORDER BY sehiradi asc
Or depending on your actual database design you might be able to simplify it to
SELECT I.id,
I.modulid,
I.id as icerikidsi,
MAX(IF(D.alanid=2,D.textkisa,NULL)) AS ilceadi,
MAX(IF(D.alanid=2,D.id,NULL)) AS ilceadi_i,
sub1.sehiradi_a ,
sub1.sehiradi_i,
sub1.sehiradi ,
I.seo_description,
I.seo_h1,
I.seo_h2,
I.seo_h3,
I.seo_h4,
I.seo_imgalt,
I.seo_imgtitle,
I.seo_keywords,
I.seo_pagetitle,
I.seo_url,
I.seo_urltitle
FROM datalar as D
LEFT JOIN icerikler as I ON D.icerikid=I.id
LEFT OUTER JOIN
(
SELECT D1.icerikid,
CONVERT ( GROUP_CONCAT(D2.id SEPARATOR ' ₋ ' ) USING UTF8 ) AS sehiradi_a,
GROUP_CONCAT(D2.textkisa SEPARATOR ' ₋ ' ) AS sehiradi,
GROUP_CONCAT(DISTINCT D1.iliskiid SEPARATOR ' ₋ ') AS sehiradi_i
FROM datalar as D1
LEFT JOIN datalar as D2 ON D1.iliskialanid=D2.id
WHERE D1.modulid='3'
AND D1.alanid='3'
GROUP BY D1.icerikid
) sub1
ON sub1.icerikid = I.id
WHERE D.modulid='3'
GROUP BY D.icerikid
ORDER BY sehiradi asc
However there is a minor issue here. In MySQL a view cannot contain a FROM that takes data from a sub query. As such to use this syntax in your view you would need to split the sub queries off into their own views. Then you could join against the view rather than the sub query.

No Join Predicate Warning - Why Does this query never complete/timeout?

Here is my query that I get a "No Join Predicate" warning:
select DISTINCT d.* from Device d , Company c1
WHERE d.CustomerID = c1.CompanyID AND c1.CompanyNumber in
(SELECT * FROM [dbo].[Split] ('56257100', ','))
OR
EXISTS ( select * from (SELECT * FROM [dbo].[Split] ('American', ',')) as s
WHERE d.CustomerID = c1.CompanyID AND c1.CompanyName like '%' + s.items + '%' )
Essentially I had two queries, and I want to join them with an OR (get the results from both). I believe it's trying to join the two queries as a Cartesian product, which isn't what I want.
If I separate it as 2 queries and UNION the results, it is fast. This however makes me re-structure my dynamic SQL quite a bit. I'd like to keep it formatted where I can have an OR there, or an AND if need be.
The parenthesis are incorrect. They should be as follows so that it knows d is the same across the OR
select DISTINCT d.* from Device d , Company c1
WHERE d.CustomerID = c1.CompanyID AND
(
c1.CompanyNumber in (SELECT * FROM [dbo].[Split] ('56257100', ','))
OR
EXISTS ( select * from (SELECT * FROM [dbo].[Split] ('American', ',')) as s
WHERE d.CustomerID = c1.CompanyID AND c1.CompanyName like '%' + s.items + '%' )
)

Nested GROUP_CONCAT query doesn't return all values

I have a query with a few subqueries, but the strange thing is that the subqueries won't return the same values as if I execute the queries one by one manually.. At first I used 'IN' inside the queries, but no indexes were used, so I converted them to '='. The results are the same with 'IN' or when I use the converted to '=' variation.
SELECT *
FROM partners
WHERE id = (
SELECT GROUP_CONCAT( partner_id
SEPARATOR ' OR id = ' )
FROM product_feeds
WHERE id = (
SELECT GROUP_CONCAT( DISTINCT feed_id
SEPARATOR ' OR id = ' )
FROM product_data
WHERE category_id = (
SELECT GROUP_CONCAT( id
SEPARATOR ' OR category_id = ' )
FROM product_categories
WHERE parent_id = (
SELECT GROUP_CONCAT( id
SEPARATOR ' OR parent_id = ' )
FROM product_categories
WHERE parent_id =1 )
ORDER BY NULL )
ORDER BY NULL )
ORDER BY NULL )
When I, for example, execute the deepest nested 3 subqueries manually, I get 10,11,12,33,34,35 as the final result. When I execute the full 3 subqueries at once, they return 10,11,12.
I am missing results..
Instead of trying to rely on GROUP_CONCAT, this is a job for INNER JOIN to get results from multiple tables where relationships exist.
SELECT
-- Best to specify the precise fields you want here instead of *
*
FROM partners p
INNER JOIN product_feeds pf
ON pf.partner_id = p.id
INNER JOIN product_data pd
ON pd.feed_id = pf.id
INNER JOIN product_categories pc
ON pc.id = pd.category_id
INNER JOIN product_categories pcparent
ON pcparent.id = pc.parent_id
AND pcparent.parent_id = 1