SQL combining multiple columns from same table while querying multiple tables - mysql

I have got three tables that looks as follows.
usedetails [ID,first_name,last_name,telephone,email]
address [ID,streetnumber,streetname,town,county,postcode,userdetailsID]
BOOKING [ID,customerID,pickup_address_id,dropoff_address_id,charge,no_of_passenger]
Address table holds two types of address ie pickoff and dropoff. I would like to display each of the two addresses as one string. The following is my query.
query = "SELECT A.streetnumber,
A.streetname,
A.town,
A.postcode
AS pickup_point
AB.streetnumber,
AB.streetname,
AB.town,
AB.postcode
AS dropoff_point
UD.first_name,
UD.last_name,
UD.telephone,
UD.email
FROM userdetails UD
INNER JOIN booking B
ON B.customerID = UD.ID
INNER JOIN address A
ON B.pickup_address_id = A.ID
INNER JOIN address AB
ON AB.drop_off_address_id = A.ID
WHERE UD.ID = A.userdetailsID OR UD.ID = AB.userdetailsID";

Try CONCAT function:
SELECT CONCAT(A.streetnumber,
' ',
A.streetname,
' ',
A.town,
' ',
A.postcode) AS pickup_point, ...
Or CONCAT_WS function to pass separator as the first argument:
SELECT CONCAT_WS(' ',
A.streetnumber,
A.streetname,
A.town,
A.postcode) AS pickup_point, ...

Related

MySQL - subquery or joining multiple rows

I got a little struggle with my mysql query. Maybe someone can help me.
Tables:
contacts:
|id|phone|first_name|last_name|email|company|
custom_values:
|id|c_id|custom_field_id|value|
The table custom_values got different custom_field_ids
id 4 = mobile
id 5 = fax
id 20 = 2nd phonenumber
The current query gives me all information from my contacts table.
concat(contacts.first_name, ' ', contacts.last_name, ' - ', contacts.company) as displayname, contacts.phone, contacts.last_name, contacts.first_name, contacts.company, contacts.email
from contacts
Now I want to add the information from the custom_values table to the query above.
Is it possible to add 3 rows, that adds me mobile, fax and the 2nd phonenomber to every contact?
I tried with the next query, but that doesn´t work.
SELECT
concat(contacts.first_name, ' ', contacts.last_name, ' - ', contacts.company) as displayname, contacts.phone, contacts.last_name, contacts.first_name, contacts.company, contacts.email,custom_values.value as mobile
from custom_values
join contacts on custom_values.customized_id = contacts.id
where custom_values.custom_field_id=4
thanks guys.
If you want additional rows, then your approach is fine. However, I think you want additional columns, not additional rows.
One approach is multiple LEFT JOIN:
select concat(c.first_name, ' ', c.last_name, ' - ', c.company) as displayname,
c.phone, c.last_name, c.first_name, c.company, c.email,
cvm.value as mobile,
cvf.value as fax,
cvp2.value as second_phone
from contacts c left join
custom_values cvm
on cvm.customized_id = c.id and
cvm.custom_field_id = 4 left join
custom_values cvf
on cvf.customized_id = c.id and
cvf.custom_field_id = 5 left join
custom_values cvp2
on cvp2.customized_id = c.id and
cvp2.custom_field_id = 20;

Find the relationship match in sql

If I got 2 table, which is
How do I get the result of
I know combine the name is using CONCAT_WS function, but I don't understand how can I exchange the row such as the "wife" and "husband" on my output.
You should join the client table two time (of of each related part in row) using tablename alias
select
concat(c1.client_firstname, ' ' , c1.client_lastname) as A_Name
, r.rel_client1_state as A_State
, concat(c2.client_firstname, ' ' , c2.client_lastname) as B_Name
, r.rel_client2_state as B_State
from relationships as r
inner join client as c1 on r.rel_client1_id = c1.client_id
inner join clinet as c2 on r.rel_client2_id = c2.client_id
SELECT CONCAT_WS(' ', c1.client_firstname, c1.client_lastname) as c1name,
r.rel_client1_state, CONCAT_WS(' ', c2.client_firstname, c2.client_lastname) as c2name,
r.rel_client2_state FROM client c1
JOIN relationship r ON c1.client_id = r.rel_client1_id
JOIN client c2 ON c2.client_id = r.rel_client2_id WHERE 1

Implementing Mysql Joins. How to get results in same row?

Link for Er Diagram:
I want to get data from the child tables.
Eg. I need location, equipments, language, service for all user_id. There are multiple values for location, equipment, language and service for a given user_id.
I tried the following code:
SELECT user_detail.user_id , user_detail.name , user_equipment.equipment , user_location.location , user_service.service , user_language.language
from user_detail
INNER JOIN user_equipment on user_detail.user_id = user_equipment.user_id
INNER JOIN user_location on user_detail.user_id = user_location.user_id
INNER JOIN user_service on user_detail.user_id = user_service.user_id
INNER JOIN user_language on user_detail.user_id = user_language.user_id;
Now the problem is, if there are three location for a user_id I get three row, is there any way I get all location in same row?
You are looking for this "GROUP_CONCAT", your query would look like this:
SELECT user_detail.user_id ,
user_detail.name,
GROUP_CONCAT(user_equipment.equipment SEPARATOR ',') as equipments,
GROUP_CONCAT(user_location.location SEPARATOR ',') as locations,
GROUP_CONCAT(user_service.service SEPARATOR ',') as services,
GROUP_CONCAT(user_language.language SEPARATOR ',') as languages
FROM user_detail
INNER JOIN user_equipment on user_detail.user_id = user_equipment.user_id
INNER JOIN user_location on user_detail.user_id = user_location.user_id
INNER JOIN user_service on user_detail.user_id = user_service.user_id
INNER JOIN user_language on user_detail.user_id = user_language.user_id;
GROUP BY user_detail.user_id
In situations where I can't use a GROUP_CONCAT call, I would do the select, then join them in some resulting code. I am unsure what application language you are using, but for something like php:
$select = $query(); //Returns the SELECT results
for($i = 0; $i < count($select); $i++){
for($a = 0; $a < count($select); $a++){ //Double loop to check the entire list
if($a !== !i){ //No point in selecting the same row and comparing it
$location_count = 0;
if($select[$a]['user_id'] === $select[$i]['user_id']){
$locationref = 'location_'.$location_count++;
$select[$i][$locationref] = $select[$a]['location'];
}
}
}
}
Just my thoughts - untested but the general principle is there.
You can reduce multiple lines to single lines for each user, by grouping by user_id. The GROUP_CONCAT function will enable you to see all values of location in the group - like so:
SELECT user_detail.user_id ,
user_detail.name ,
user_equipment.equipment ,
GROUP_CONCAT(user_location.location SEPARATOR ',') AS user_locations ,
user_service.service ,
user_language.language
from user_detail
INNER JOIN user_equipment on user_detail.user_id = user_equipment.user_id
INNER JOIN user_location on user_detail.user_id = user_location.user_id
INNER JOIN user_service on user_detail.user_id = user_service.user_id
INNER JOIN user_language on user_detail.user_id = user_language.user_id
GROUP BY user_detail.user_id;
Note that this assumes there will always be one (and only one) equipment, service and language record for each user - if there can be more than one of each then you should use GROUP_CONCAT for their values (with a DISTINCT qualifier), while if the user might not have corresponding records the join to the relevant table should be changed to a LEFT OUTER JOIN.

How to consolidate in a query?

I need some help writing a query to consolidate names into a list that are associated with a foreign key. Here's my current query,
select distinct concat(c_first, ' ', c_last) as name, pmt_no
from disbursements d
left join contacts c on c.c_no = d.b_no
where d.ba_no = 1
My result set looks like this
Louis Vaz, 586014
Antionette An, 690682
Brian Cald, 690682
Mark Brian, 3233902
My desired outcome is
Louis Vaz, 586014
Antionette An - Brian Cald, 690682
Mark Brian, 3233902
Please note that both the people with pmt_no 690682 are now joined together with a '-' separating them.
You can use the GROUP_CONCAT() function to achieve what you want:
select group_concat(distinct concat(c_first, ' ', c_last) SEPARATOR ' - ') as name, pmt_no
from disbursements d
left join contacts c on c.c_no = d.b_no
where d.ba_no = 1
group by pmt_no
I think you want group_concat() along with a group_by:
select group_concat(c_first, ' ', c_last separator ' - ') as names,
pmt_no
from disbursements d left join
contacts c
on c.c_no = d.b_no
where d.ba_no = 1
group by pmt_no;

MYSQL table pivot manually to automatic

I'm trying to pivotise my columns to get from rows to tables.
It's working like expected with the code I have now, but when my fields get updated I have to manually edit the query in order to update it.
I'm trying to automate the process but I'm not getting it to work. Any ideas?
This is the manual code which works:
SELECT
md.entity_guid AS guid, username, e.time_created, time_updated, e.enabled, banned,e.last_action, last_login,
MAX(IF(msn.string = 'question1', msv.string, NULL)) AS question1
FROM exp_metadata md
JOIN exp_metastrings msn ON md.name_id = msn.id
JOIN exp_metastrings msv ON md.value_id = msv.id
JOIN exp_users_entity u ON u.guid = md.entity_guid
JOIN exp_entities e ON e.guid = md.entity_guid
GROUP BY
guid
And this is the query I'm trying to do to automate it:
SET #sql = NULL;
SELECT
md.entity_guid AS guid, username, e.time_created, time_updated, e.enabled, banned, e.last_action, last_login,
GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(IF(msn.string = ''',
msn.string,
''', msv.string, NULL)) AS ',
msn.string
)
) INTO #sql
FROM exp_metadata md
JOIN exp_metastrings msn ON md.name_id = msn.id
JOIN exp_metastrings msv ON md.value_id = msv.id
JOIN exp_users_entity u ON u.guid = md.entity_guid
JOIN exp_entities e ON e.guid = md.entity_guid
SET #sql = CONCAT('SELECT e.guid, ', #sql, ' FROM exp_entities e GROUP BY e.guid');
I get an error in phpmyadmin about the last line.
When I delete the last line to see if it does anything, I get:
#1222 - The used SELECT statements have a different number of columns
Any help would be appreciated.
Thanks a lot, Dries