mysql multiple-subquery group_concat query - mysql

I'm trying to show the boroughs and postcodes a particular town in is.
My database is fairly well structured, with a table such as town, postcode and borough. There are also tables for each of the relationships town_postcode & town_borough.
Ideally I want the data returned as:
"Abbey Wood", "SE2", "Bexley, Greenwich"
"Barbican", "EC1, EC2", "City of London"
I've tried a few different approaches and I'm close but not there yet.
Any help would be appreciated... :)
So far I've tried
SELECT DISTINCT t.town,
GROUP_CONCAT( DISTINCT p.postcode SEPARATOR ', ' ) AS 'postcode',
GROUP_CONCAT( DISTINCT b.borough SEPARATOR ', ' ) AS 'borough'
FROM coverage_towns AS t,
coverage_boroughs AS b,
coverage_postcodes AS p,
coverage_towns_boroughs AS tb,
coverage_towns_postcodes AS tp
WHERE t.id = tp.town_id
AND p.id = tp.postcode_id
AND b.id = tb.borough_id
GROUP BY t.town
ORDER BY t.town ASC
Which returns
"Abbey Wood", "SE2", "Southwark, Hammersmith and Fulham, Tower Hamlets, Wandsworth, Enfield, Newham, LOTS MORE HERE"
"Barbican", "EC1, EC2", "Brent, Greenwich, Kensington and Chelsea, Westminster, Camden, LOTS MORE HERE"
I've also tried
SELECT DISTINCT t.town, (
SELECT SQL_CACHE DISTINCT GROUP_CONCAT( p1.postcode
SEPARATOR ', ' )
FROM coverage_postcodes AS p1
WHERE p1.id = tp.postcode_id
) AS 'postcode', (
SELECT SQL_CACHE DISTINCT GROUP_CONCAT( b1.borough
SEPARATOR ', ' )
FROM coverage_boroughs AS b1
WHERE b1.id = tb.borough_id
) AS 'borough'
FROM coverage_towns AS t, coverage_boroughs AS b, coverage_postcodes AS p, coverage_towns_boroughs AS tb, coverage_towns_postcodes AS tp
WHERE t.id = tp.town_id
AND p.id = tp.postcode_id
AND b.id = tb.borough_id
GROUP BY t.town
ORDER BY t.town ASC
Which returns
"Abbey Wood", "SE2", "Greenwich"
"Acton", "W3", "Greenwich"
"Aldersbrook", "E12", "Greenwich"

First query looks good, just add distinct inside the group_concat, like:
SELECT t.town
, GROUP_CONCAT(DISTINCT p.postcode SEPARATOR ', ' ) AS 'postcode'
, GROUP_CONCAT(DISTINCT b.borough SEPARATOR ', ' ) AS 'borough'
<more code here>
GROUP BY
t.town

SOLUTION
I came back to the question after a good coffee and the answer presented itself.
SELECT DISTINCT t.town,
GROUP_CONCAT( DISTINCT p.postcode SEPARATOR ', ' ) AS 'postcode',
GROUP_CONCAT( DISTINCT b.borough SEPARATOR ', ' ) AS 'borough'
FROM towns AS t, boroughs AS b, postcodes AS p, towns_boroughs AS tb, towns_postcodes AS tp
WHERE (t.id = tp.town_id AND t.id = tb.town_id)
AND (p.id = tp.postcode_id AND b.id = tb.borough_id)
GROUP BY t.town
ORDER BY t.town ASC

Related

MYSQL select using concat with not in statment

can someone correct me on this syntax error. am trying to search users by firstname, lastname and their email
SELECT
USERID,
FNAME,
LNAME
FROM
USERS
WHERE
CONCAT(FNAME, ', ', LNAME, ', ', EMAIL) LIKE CONCAT('%', REPLACE('keyword ', ' ', '%'), '%', '%') NOT IN (
SELECT
PRODUCT_ID
FROM
ITEMS
WHERE
USER = 'JANE'
AND PRICE = '400'
AND ORDER = 'PAID'
)
i want to search and get userid,firstname and lastname. but i dont want to get jane, price = 400 and order = paid
TABLE USER
USERID FNAME LNAME EMAIL
1 JANE DEO TES#TED.COM
2 KEL DEO TES#TED.COM
3 MK DEO TES#TED.COM
TABLE ITEMS
PRODUCT_ID PRICE ITEM_NUM USER USERID
1 400 40 JANE 1
2 200 20 KEL 2
3 100 10 MK 3
so i want to get the rest people apart from JANE ROW
AND MY TRY IS
SELECT SND.USERID, SND.FNAME, SND.LNAME WHERE CONCAT(FNAME, ', ', LNAME, ', ', EMAIL) LIKE CONCAT('%', REPLACE('keyword', ' ', '%'), '%', '%') FROM items as M JOIN users as SND ON SND.USERID WHERE NOT EXISTS(SELECT * FROM ITEMS WHERE M.USER = 'JANE' AND M.PRICE ='400' AND M.ITEM_NUM ='40')
You cannot include a where clause between the select and the from clauses
SELECT
SND.USERID
, SND.FNAME
, SND.LNAME
>> no where clause here
FROM items AS M
INNER JOIN users AS SND ON SND.USERID
WHERE NOT EXISTS (
SELECT *
FROM ITEMS
WHERE M.USER = 'JANE'
AND M.PRICE = '400'
AND M.ITEM_NUM = '40'
)
Just include all the wanted conditions int the one (and only) where clause, combine those using AND's or OR's as needed. I have changed the join condition, and altered the NOT syntax used also.
SELECT
SND.USERID
, SND.FNAME
, SND.LNAME
FROM items AS M
INNER JOIN users AS SND ON M.userid = SND.userid
WHERE CONCAT(FNAME, ', ', LNAME, ', ', EMAIL) LIKE CONCAT('%', REPLACE('keyword', ' ', '%'), '%', '%')
AND NOT (
M.USER = 'JANE'
AND M.PRICE = '400'
AND M.ITEM_NUM = '40'
)
I'm not that comfortable with your use of concat() in the above however, it looks very inefficient, instead why not just repeat the LIKE tests on each column. (Yes it may make the SQL code longer, but that is not an indicator of the execution time of the query.)
SELECT
SND.USERID
, SND.FNAME
, SND.LNAME
FROM items AS M
INNER JOIN users AS SND ON M.userid = SND.userid
WHERE (
SND.FNAME LIKE CONCAT('%', REPLACE('keyword', ' ', '%'))
or SND.LNAME LIKE CONCAT('%', REPLACE('keyword', ' ', '%'))
or SND.EMAIL LIKE CONCAT('%', REPLACE('keyword', ' ', '%'))
)
AND NOT (
M.USER = 'JANE'
AND M.PRICE = '400'
AND M.ITEM_NUM = '40'
)
Note the use of indents and parentheses when using or in a where clause. (You do not have to place SQL into one row, not sure why you did that in the question.)

Whats wrong I get all the names twice?

I get the names twice and I need them to appear only once instead. How can I fix it?
I am using the SQL SELECT, stated below:
SELECT
( LTRIM(SUBSTRING(resource.name, CHARINDEX(',', resource.name) + 1, LENGTH(resource.name) - CHARINDEX(',', resource.name)))) AS firstname,
(SELECT GROUP_CONCAT(SUBSTRING(REPLACE(resource.name, '*Deleted*', '') FROM 1 FOR POSITION(',' IN REPLACE(resource.name, '*Deleted*', '' ))-1))) AS lastname,
(SELECT GROUP_CONCAT(obj SEPARATOR ', ') FROM rel_raci resource_raci_r WHERE resource_raci_r.PERSON_ID = resource.id AND resource_raci_r.RACI ='R' AND getOrgtype(obj_id) = 6 ) AS companycode,
(SELECT GROUP_CONCAT(REPLACE(obj, '*Deleted*', '')) FROM rel_raci resource_raci_r WHERE resource_raci_r.PERSON_ID = resource.id AND resource_raci_r.RACI ='R' AND getOrgtype(obj_id) = 4 ) AS organizationalunit,
(SELECT GROUP_CONCAT(obj SEPARATOR ', ') FROM rel_raci resource_raci_r WHERE resource_raci_r.RACI ='R' ) AS responsible,
resource.identifier AS identifier,
resource.phone AS phone,
organisation.keywords AS keywords,
resource.keywords AS persno,
resource.id AS obj_id,
resource.mobile AS mobile,
resource.e_mail AS email,
resource.alias AS alias,
resource.city AS city,
resource.postcode AS postcode,
resource.state AS state,
resource.street AS street,
resource.country AS country
FROM obj_resource resource
LEFT OUTER JOIN rel_raci resource_raci ON resource.ID = resource_raci.PERSON_ID
LEFT OUTER JOIN obj_resource organisation on organisation.ID = resource_raci.OBJ_ID
-- Gibt nur die markierten Massnahmen aus
WHERE CONTAINS($P{TE_SELECTIONS}, resource.id, -1)

sql string can't get right

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.)

unknown column in IN/ALL/ANY subquery where clause

Problem:
I know it's documented in MYSQL DOCUMENTS That in where clause "alias" cannot be used since where clause is not populated yet. But i have to get the data matched from other table values in where clause (IN condition).
I have also read some similar kind of post but this one is quite different & big complex one. I couldn't make it working with my efforts of last 3 days.
It's showing error (excepted as per documentation)
UNKNOWN COLUMN "Ind_ID" in WHERE CLAUSE
I have to match similarly for FA_ID & PREFERRED_LOCATION_ID field
Select a.job_id, a.Employer_ID, a.Sub_user_id,
Date_format(a.creation_on,'%d-%m-%Y') as Created_date, a.Job_type,
a.Designation, a.Open_Positions, a.Job_Description, a.Min_age,
a.Max_age, a.min_exp, a.max_exp, a.Hide_Salary, a.company_name,
a.About_Company, a.Contact_person_name, a.Contact_No, a.Refresh_type,
a.Response_type,
(Select GROUP_CONCAT(DISTINCT g.Education ORDER BY pjedu.Education_ID
SEPARATOR ', ') user_education
from e_pj_edu pjedu
INNER JOIN education g ON FIND_IN_SET(g.Edu_ID, pjedu.Education_ID)
where a.job_id = pjedu.Job_ID
) as Education_ID,
(Select GROUP_CONCAT(DISTINCT h.FA_description ORDER BY uf.FA_ID
SEPARATOR ', ') FA
from e_pj_fa uf
INNER JOIN functional_area h ON FIND_IN_SET(h.FA_ID, uf.FA_ID)
where a.Job_ID = uf.Job_ID
) as FA_ID,
(Select GROUP_CONCAT(DISTINCT i.Industry_description ORDER BY
ui.Industry_ID SEPARATOR ', ') Industry_ID
from e_pj_industry ui
INNER JOIN industry i ON FIND_IN_SET(i.Industry_ID, ui.Industry_ID)
where a.Job_ID = ui.Job_ID
) as Ind_ID,
(Select GROUP_CONCAT(DISTINCT j.location_name ORDER BY
upl.Location_ID SEPARATOR ', ') Location_ID
from e_pj_locations upl
INNER JOIN locations j ON FIND_IN_SET(j.location_id, upl.Location_ID)
where a.Job_ID = upl.Job_ID
) as Preferred_Location_ID,
(Select GROUP_CONCAT(DISTINCT uk.Keyword_Name ORDER BY uk.Keyword_ID
SEPARATOR ', ') keyskills
from e_pj_keywords uk
where a.Job_ID = uk.Job_ID
) as Keyword_Name,
GROUP_CONCAT(DISTINCT cc.salary_description ORDER BY cc.salary_ID
SEPARATOR ', ') Min_salary,
GROUP_CONCAT(DISTINCT dd.salary_description ORDER BY dd.salary_ID
SEPARATOR ', ') Max_salary
from post_jobs a
INNER JOIN user_salary cc ON FIND_IN_SET(cc.salary_ID, a.Min_salary)
INNER JOIN user_salary dd ON FIND_IN_SET(dd.salary_ID, a.Max_salary)
WHERE a.Designation LIKE '%MIS%' or a.company_name LIKE '%MIS%'
And a.max_exp <= 9
And a.Max_salary<=110
And Ind_ID IN (10001,10002,10004)
And FA_ID IN(1001)
group by a.job_id
First thing that comes in my mind is just move your aliased where conditions to outer query, i.e.:
select * from (
Select a.job_id ....
WHERE a.Designation LIKE '%MIS%' or a.company_name LIKE '%MIS%'
And a.max_exp <= 9
And a.Max_salary<=110
group by a.job_id
) inner
where
Ind_ID IN (10001,10002,10004)
And FA_ID IN(1001)
GL!
Posting revised query which worked. May be this helps someone from wasting 3 days like me :-)
select * from (
Select a.job_id, a.Employer_ID, a.Sub_user_id, Date_format(a.creation_on,'%d-%m-%Y') as Created_date, a.Job_type, a.Designation, a.
Open_Positions, a.Job_Description, a.Min_age, a.Max_age, a.min_exp, a.max_exp, a.Hide_Salary, a.company_name, a.About_Company, a.Contact_person_name,
a.Contact_No, a.Refresh_type, a.Response_type,
(Select GROUP_CONCAT(DISTINCT g.Education ORDER BY pjedu.Education_ID SEPARATOR ', ') user_education
from e_pj_edu pjedu
INNER JOIN education g ON FIND_IN_SET(g.Edu_ID, pjedu.Education_ID)
where a.job_id = pjedu.Job_ID
) as Education_ID,
(Select GROUP_CONCAT(DISTINCT h.FA_description ORDER BY uf.FA_ID SEPARATOR ', ') FA
from e_pj_fa uf
INNER JOIN functional_area h ON FIND_IN_SET(h.FA_ID, uf.FA_ID)
where a.Job_ID = uf.Job_ID
) as FA_ID,
(Select GROUP_CONCAT(DISTINCT i.Industry_description ORDER BY ui.Industry_ID SEPARATOR ', ') Industry_ID
from e_pj_industry ui
INNER JOIN industry i ON FIND_IN_SET(i.Industry_ID, ui.Industry_ID)
where a.Job_ID = ui.Job_ID
) as Ind_ID,
(Select GROUP_CONCAT(DISTINCT j.location_name ORDER BY upl.Location_ID SEPARATOR ', ') Location_ID
from e_pj_locations upl
INNER JOIN locations j ON FIND_IN_SET(j.location_id, upl.Location_ID)
where a.Job_ID = upl.Job_ID
) as Preferred_Location_ID,
(Select GROUP_CONCAT(DISTINCT uk.Keyword_Name ORDER BY uk.Keyword_ID SEPARATOR ', ') keyskills
from e_pj_keywords uk
where a.Job_ID = uk.Job_ID
) as Keyword_Name,
GROUP_CONCAT(DISTINCT cc.salary_description ORDER BY cc.salary_ID SEPARATOR ', ') Min_salary,
GROUP_CONCAT(DISTINCT dd.salary_description ORDER BY dd.salary_ID SEPARATOR ', ') Max_salary
from post_jobs a
INNER JOIN user_salary cc ON FIND_IN_SET(cc.salary_ID, a.Min_salary)
INNER JOIN user_salary dd ON FIND_IN_SET(dd.salary_ID, a.Max_salary)
group by a.Job_id
) aa
WHERE Designation LIKE '%op%' or company_name LIKE '%op%'
And max_exp <= 15
And Max_salary<=120
and Ind_ID IN (10001,10002,10004,10003)
And FA_ID IN(1001,1002,1003)
group by Job_id

Merging two queries into One

Here's my code:
$queryresult="SELECT a.ArticleID, a.Title, a.Publication, l.EnglishLanguage, m.EnglishMedia, a.PublicationYear, a.Size , REPLACE( GROUP_CONCAT( DISTINCT REPLACE( c.EnglishCategory, ',', '' ) ) , '/', ',' ) , GROUP_CONCAT( DISTINCT au.EnglishName, '/' ), GROUP_CONCAT( DISTINCT au.PictureURL ) , a.Abstract,a.URL,m.IconURL,REPLACE( GROUP_CONCAT( DISTINCT REPLACE( au.EnglishName, ',', '' ) ) , '/', ',' )
FROM article a
LEFT JOIN aritcletocategory ac ON a.ArticleID = ac.ArticleID
LEFT JOIN category c ON ac.CategoryID = c.CategoryID
LEFT JOIN articletoauthor at ON a.ArticleID = at.ArticleID
JOIN MediaType m ON a.MediaTypeID = m.MediaTypeID
JOIN Language l ON a.LanguageID = l.LanguageID
LEFT JOIN author au ON at.AuthorID = au.AuthorID
WHERE a.Title REGEXP '".$search."' || replace(au.EnglishName,',','') REGEXP '".$search."' || replace(au.HebrewName,',','') REGEXP '".$search."' || a.Keywords REGEXP '".$search."'|| c.EnglishCategory REGEXP '".$search."' || a.Abstract REGEXP '".$search."'|| a.Publication REGEXP '".$search."'GROUP BY a.ArticleID";
$finalresult=show_result($queryresult);
And the Id I got from result of this query is used in the following query:
foreach($finalresult as $ress){
$queryresults="SELECT a.ArticleID, a.Title, a.Publication, l.EnglishLanguage, m.EnglishMedia, a.PublicationYear, a.Size , REPLACE( GROUP_CONCAT( DISTINCT REPLACE( c.EnglishCategory, ',', '' ) ) , '/', ',' ) , GROUP_CONCAT( DISTINCT au.EnglishName , '/' ), GROUP_CONCAT( au.PictureURL ) , a.Abstract,a.URL, REPLACE( GROUP_CONCAT( DISTINCT REPLACE( au.HebrewName, ',', '' ) ) , '/', ',' ),m.IconURL,REPLACE( GROUP_CONCAT( DISTINCT REPLACE( au.EnglishName, ',', '' ) ) , '/', ',' )
FROM article a
LEFT JOIN aritcletocategory ac ON a.ArticleID = ac.ArticleID
LEFT JOIN category c ON ac.CategoryID = c.CategoryID
LEFT JOIN articletoauthor at ON a.ArticleID = at.ArticleID
LEFT JOIN author au ON at.AuthorID = au.AuthorID
JOIN MediaType m ON a.MediaTypeID = m.MediaTypeID
JOIN Language l ON a.LanguageID = l.LanguageID
WHERE a.ArticleID =".$ress[0]." GROUP BY a.ArticleID ";
$finalresults=show_result($queryresults);
I wish to get the result with one query rather than using two queries. How can I do that?
As your queries have the same structure you can use UNION
--Query 1
SELECT ...
UNION
--Query 2
SELECT ...
;
Check out w3schools - SQL UNION Operator for more information.
Or if you want to get more professional information: MySQL Manual: Union Syntax