Mysql combining multiple rows into one row dependant upon a single field? - mysql

I have three tables, table one (tableA) containing users data like name and email, another (tableB) flagging if they wish to receive an email or sms notice and a last table (tableC) noting which type of notices they require out of four types.
tableA and tableB have single rows for each user, but tableC could have up to 4 entries.
Is it possible I can concatinate the multiple entries of tableC in to a single row return, additionally with my other data from my other two tables. Perhaps building some sort of comma delimited field in the row?
I currently have this as my mySQL query:
SELECT
ppf.page_id,
prv.`name`,
prv.surname,
prv.email,
prv.mobile,
ppf.email,
ppf.sms,
page_profile_noticetypes.noticetype
FROM
page_registration_value AS prv
Inner Join page_profile_value AS ppf ON prv.page_id = ppf.user
Inner Join page_profile_noticetypes ON page_profile_noticetypes.page_id = ppf.page_id
WHERE ppf.sms = 1 OR ppf.email = 1

#itsadok answered it - Result:
SELECT
ppf.page_id,
prv.`name`,
prv.surname,
prv.email,
prv.mobile,
ppf.email,
ppf.sms,
GROUP_CONCAT(page_profile_noticetypes.noticetype)
FROM
page_registration_value AS prv
Inner Join page_profile_value AS ppf ON prv.page_id = ppf.user
Inner Join page_profile_noticetypes ON page_profile_noticetypes.page_id = ppf.page_id
WHERE ppf.sms = 1 OR ppf.email = 1
GROUP BY prv.email

Related

SQL QUERY - Merge Table

I have a three tables.
Alan1, Alan2, Alan3 are the same in all tables.I want to merge tables. The difference of the tables is the rightmost column. How should I write a SQL Query?
You can join. As commented by Barmar, the idea is to use the first 3 columns as join keys;
select a.*, b.alan4 as alan4b, c.alan4 as alan4c
from a
inner join b
on b.alan1 = a.alan1
and b.alan2 = a.alan2
and b.alan3 = a.alan3
inner join c
on c.alan1 = a.alan1
and c.alan2 = a.alan2
and c.alan3 = a.alan3
This gives you rows that are available in all 3 tables. Say you want to allow "missing" rows in b and/or c, then you need to change the two inner joins to left joins.

How to remove duplicate concat extract from number in MySQL

I want to retrieve text data in the form of numbers from MySQL, but the query that I made actually creates duplicate data,
SELECT a.* FROM users a
LEFT JOIN projects b
ON CONCAT(',',b.team,',') LIKE CONCAT('%',a.id,'%')
WHERE b.id = ${params.project_id}
GROUP BY a.id)
For example: mysql 1,13 instead appears 1,1,13 every two digits then appears duplicate

Reading multiple fields on one table and joining them single line records from another table

I have two tables A and B. A has unique records while B may have several references to one record in A.
A table -> A.UserID,A.Image1.ID,A.Image2.ID,A.UserName
B table -> B.ImageID,B.ImageURL,ImageDescription
B. Image ID is unique and could have at least two records correspond to Image!ID and Image2ID in table A.
In my query, need to read A.UserName,B.Image1URL and B.Image2URL.
Following SQL query is to read one image. How I could modify this to read both Image1 and Image2 in one SQL query ?.
#"SELECT A.*,B.* FROM A
INNER JOIN B ON B.Image1ID = A.Image1ID
WHERE A.UserID = #Parameter1;";
So in the result, I need following :
UserID
Image1URL
Image2URL
What's the best way to get this done in mySQL ?
You can join same table twice -
SELECT A.UserID, A.UserName, img1.ImageURL, img2.ImageURL
FROM A
INNER JOIN B as img1
ON img1.ImageID = A.Image1ID
INNER JOIN B as img2
ON img2.ImageID = A.Image2ID
WHERE A.UserID = #Parameter1;

mysql return rows from table 1 based on values in either column 1 or column 2 in table 2

I have two tables: 'tasknotes' and 'relatedtasks'.
I want to return all the rows from 'tasknotes' in which the values in its'task_id' column corresponds to the values held in one of two columns in the 'relatedtasks' table. The columns from the 'relatedtasks' table which hold these values are called 'primarytaskid' and 'relatedtaskid'
I want to return values from the 'tasknotes' if the 'tasknotes.task_id' matches the value stored in either relatedtasks.primarytaskid or relatedtasks.relatedtaskid
I tried to do it several ways. I've been looking at the example here as I thought it might help:
Selecting rows from one table using values gotten from another table MYSQL
But I can't get it quite right. I've also tried the following but I can't seem to get it to work.
"Select * from tasknotes WHERE tasknotes.task_id = ? AND relatedtasks.primarytaskid = ? OR relatedtasks.relatedtaskid= ?";
How should I be dong this? I recognise an option would be to create a version of this code:
SELECT t1.* FROM film t1 WHERE EXISTS (SELECT filmid
FROM film_rating_report t2
WHERE t2.rating = 'GE'
AND t2.filmid = t1.id);
which is from the other stack answer I cited and then run it twice targeting each column distinctly, but there must be a better solution.
********** RESOLVED CODE *****************
Thanks to the answer and comments below the final code is:
String sql = "SELECT t.* "
+ "FROM tasknotes t "
+ "INNER JOIN relatedtasks r "
+ "ON (t.task_id = r.primarytaskid OR t.task_id = r.relatedtaskid) "
+ "WHERE r.primarytaskid=? OR r.relatedtaskid=?";
the values for the '?' as passed in from statements in the java code.
This is a job for a JOIN with a nontrivial ON clause.
Try something like this:
SELECT t.*
FROM tasknotes t
JOIN relatedtasks r
ON (t.task_id = r.primarytask OR t.task_id = r.relatedtaskid)
Using JOIN rather than LEFT JOIN will suppress the rows from tasknotes that don't meet the ON clause.
If you need to filter, append a WHERE clause to the query. For example:
SELECT t.*
FROM tasknotes t
JOIN relatedtasks r
ON (t.task_id = r.primarytask OR t.task_id = r.relatedtaskid)
WHERE t.task_id = ?
The trick here:
All the FROM / JOIN ON stuff is to be considered a chunk of code. It specifies the table (physical or virtual) in your query. In your query your virtual table is
FROM tasknotes t
JOIN relatedtasks r
ON (t.task_id = r.primarytask OR t.task_id = r.relatedtaskid)
This virtual table has both tasknotes and relatedtasks columns in it. It has all possible combinations of rows from the two tables that match the ON clause.
(If you did FROM a JOIN b without an ON clause you would get all combinations of rows in a and b. That could be a great many rows.)
You put a SELECT clause before your virtual table to choose the columns you want to retrieve from that virtual table.
You put a WHERE clause after it to choose the rows you want from your virtual table.
In your case you may need SELECT DISTINCT t.* because your virtual table will have a row for each row in tasknotes times each matching row in relatedtasks.
Finally you let the query planner in MySQL figure out how to satisfy your query efficiently.

What is the proper syntax for multiple left join and where condition on the left table?

The following select statement returns zero results, why?
SELECT `post_job`.`id`,
`post_job_description`.`title`,
`employers_description`.`name`
FROM (`post_job`)
LEFT JOIN `post_job_description`
ON `post_job`.`id` = `post_job_description`.`post_job_id`
LEFT JOIN `employers_description`
ON `post_job`.`employers_id` = `employers_description`.`id`
WHERE `post_job`.`published` = 1
AND `post_job_description`.`language` IN ('en')
AND `employers_description`.`language` IN ('en')
AND `post_job`.`deleted` = 0
GROUP BY `post_job_description`.`post_job_id`
LIMIT 25
When I remove this:
AND `employers_description`.`language` IN ('en')
it return data but the value of employers_description.name is not in English
post_job table:
post_job_description table:
employers_description table:
This ON clause:
`post_job`.`employers_id` = `employers_description`.`id`
is used to join employers_description table to post_job table.
Just a single row is being selected from post_job table (according to your posted sample data):
id employers_id published deleted
---------------------------------
1 2 1 0
As per the above mentioned ON clause, the following one and only row from employers_description is being fetched by the LEFT JOIN:
name id language
-----------------
MaIT ar 2 ar
Hence, this predicate:
`employers_description`.`language` IN ('en')
filters this row out, and you get no results. If you take this predicate out of the WHERE clause, then you get this row returned, but, as you can see from above, language = ar.
You have to change the id value of record with name = MaIT ar from 2 to 1, so that both language versions from employers_description are fetched by the LEFT JOIN operation (as is the case in post_job_description table).
As a side note, perhaps you should consider normalizing post_job_description and employers_description tables by keeping language per post and language per employee info in separate tables.
Any conditions on the table that you're joining with LEFT JOIN must be put into the ON clause. If you put it in the WHERE clause, the null values that are returned for rows with no match will not match this condition, and they'll filter the whole row out.
Also, your GROUP BY column should be from the main table, not one of the LEFT JOIN tables. Otherwise, all the rows with null matches will be grouped together.
So change it to
SELECT `post_job`.`id`,
`post_job_description`.`title`,
`employers_description`.`name`
FROM (`post_job`)
LEFT JOIN `post_job_description`
ON `post_job`.`id` = `post_job_description`.`post_job_id`
AND `post_job_description`.`language` IN ('en')
LEFT JOIN `employers_description`
ON `post_job`.`employers_id` = `employers_description`.`id`
AND `employers_description`.`language` IN ('en')
WHERE `post_job`.`published` = 1
AND `post_job`.`deleted` = 0
GROUP BY `post_job`.`post_job_id`
LIMIT 25