Adding a space seperating string - sql

How to add space between two name columns concatenated in SQL ?
SELECT CONCAT(a.first_name, a.last_name), f.title, f.description, f.length
FROM actor a
JOIN film_actor fa
ON a.actor_id = fa.actor_id
JOIN film f
ON f.film_id = fa.film_id
snapshot of result of query
i want to have space between names like "PenelopeGuiness" to "Penelope Guiness"

I tried to add ' ' inside CONCATE parameters but id did not work!
Anyway, I just found below solution and it worked.
SELECT a.first_name || ' ' || a.last_name AS full_name

Each of these concatenates a space character in between:
first_name || ' ' || last_name
concat(first_name, ' ', last_name)
concat_ws(' ', first_name, last_name)
(The first form with basic concatenation operator being very slightly cheaper.)
But each form handles NULL input differently. You typically want "NULL-safe" concatenation with concat_ws() if that can happen. Detailed assessment:
Combine two columns and add into one new column

SELECT CONCAT(a.first_name, " ", a.last_name), f.title, f.description, f.length
FROM actor a
JOIN film_actor fa
ON a.actor_id = fa.actor_id
JOIN film f
ON f.film_id = fa.film_id

Related

Relational Division in SQL

Writing a SQL query to list the fullname ('<first_name> <last_name>') of every actor who acted in every film which had a title starting with 'CHOCOLAT':
Here is my approach:
SELECT
actor_id, first_name || ' ' || last_name AS fullname
FROM
Actor A
WHERE
NOT EXISTS (SELECT film_id
FROM Film F
WHERE title LIKE 'CHOCOLAT%'
EXCEPT
SELECT film_id
FROM Film_Actor FA
WHERE FA.actor_id = A.actor_id)
ORDER BY
fullname
The problem with this approach is that when there is no film which had a title starting with 'CHOCOLAT%', it lists all the actors instead of returning an empty table.
The query selects the matching films and removes for each actor the film that the actor acts in. If a film remains, the actor is not acting in the film so he must not be present in the final result.
SELECT actor_id,
first_name || ' ' || last_name AS fullname
FROM Actor A
WHERE NOT EXISTS(SELECT film_id
FROM Film F
WHERE title LIKE 'CHOCOLAT%' -- select all matching films
EXCEPT
SELECT film_id
FROM Film_Actor FA
WHERE FA.actor_id = A.actor_id -- remove the films the actor acts in
) -- have a set of films the actor does not act in
-- if there is no matching film the actor does not act in,
-- (i.e. he acts in all of them) he needs to be selected
and (SELECT count(film_id)
FROM Film F
WHERE title LIKE 'CHOCOLAT%') > 0
-- special case, when there is no matching film at all:
-- The list of films the actor does not act in would be empty for every actor
-- Thus, the result would be all actors
ORDER BY fullname;
Basically, you could just add another if-clause that requires at least one matching film to be present. You could do this with count() > 0 or exists(...).

How to still return psql query if value in row is null (value also linked to other row)

I have two tables in postgres db. Companies and bootcampers. Companies.company_id is primary key to bootcampers.company_id foreign key.
Trying to select all rows from bootcampers and company_id and company_name from companies based on company_id. Some bootcampers will not have a company_id yet. How can i change this psql query to say please return all fields but if company_id is blank, return everything else anyway. Is there a 'null is ok' thing i need to use?
SELECT uid,
email,
photourl,
first_name,
surname,
aboutme,
job_title,
company_name,
salary,
start_date,
previous_roles,
cohort_num,
region,
job_satisfaction,
new_job,
bootcampers.twitter,
github,
portfolio,
bootcampers.linkedin
FROM companies
INNER JOIN bootcampers ON bootcampers.company_id = companies.company_id
WHERE first_name ILIKE '%' || $1 || '%'
Since you want everything from Bootcampers you need a RIGHT JOIN instead of an INNER JOIN
SELECT uid,
email,
photourl,
first_name,
surname,
aboutme,
job_title,
company_name,
salary,
start_date,
previous_roles,
cohort_num,
region,
job_satisfaction,
new_job,
bootcampers.twitter,
github,
portfolio,
bootcampers.linkedin
FROM companies
RIGHT JOIN bootcampers ON bootcampers.company_id = companies.company_id
WHERE first_name ILIKE '%' || $1 || '%'
Be careful if you want to add a filter on a column from the companies table as that could negate your RIGHT JOIN and make it work like an INNER again.

GROUP_CONCAT being weird

I use three tables with an inner join on 'user.ID'='email.ID' and 'user.ID'='telephone.ID'.
Every user has a name and an ID. Each email has a username, the email address itself and a corresponding userID. Each telephone number has a username, the number itself and a corresponding userID. It is possible for a user to have any amount of email addresses and telephone numbers.
I managed to output a users email addresses by selecting them like this:
GROUP_CONCAT(email.Address SEPARATOR ',') AS Address,
GROUP_CONCAT(email.Username SEPARATOR ',') AS eUsername
I then converted it into an array:
$Address = explode(",", $row["Address"]);
$eUsername = explode(",", $row["eUsername"]);
And printed it like this:
for($i = 0;$i<count($Address);$i++) {
echo $eUsername[$i] .': '. $Address[$i].'<br>';
}
This is the printed table:
I then just did the same thing with the telephone numbers
Selecting:
GROUP_CONCAT(telephone.Number SEPARATOR ',') AS Number,
GROUP_CONCAT(telephone.Username SEPARATOR ',') AS tUsername
Converting:
$Number = explode(",", $row["Number"]);
$tUsername = explode(",", $row["tUsername"]);
Printing:
for($i = 0;$i<count($Number);$i++) {
echo $tUsername[$i] .': '. $Number[$i].'<br>';
}
But this messed up the whole table:
I don´t get why it prints the email addresses three times and just doesn´t print anything in the 'Telephone' coloumn although the second for loop is echoed into the most right coloumn.
Sorry for the long post and thanks for any help.
EDIT:
Here is my full SQL query:
SELECT user.Name AS Name, user.ID AS ID,
GROUP_CONCAT(email.Address SEPARATOR ',') AS Address,
GROUP_CONCAT(email.Username SEPARATOR ',') AS eUsername,
GROUP_CONCAT(telephone.Number SEPARATOR ',') AS Number,
GROUP_CONCAT(telephone.Username SEPARATOR ',') AS tUsername
FROM user
INNER JOIN email ON user.ID=email.ID
INNER JOIN telephone ON user.ID=telephone.ID
WHERE Name REGEXP '$searchterm'
GROUP BY ID
The WHERE statement is not final. This is just for testing.
The simplest solution is to use distinct:
SELECT u.Name AS Name, u.ID AS ID,
GROUP_CONCAT(DISTINCT e.Address SEPARATOR ',') AS Address,
GROUP_CONCAT(DISTINCT e.Username SEPARATOR ',') AS eUsername,
GROUP_CONCAT(DISTINCT t.Number SEPARATOR ',') AS Number,
GROUP_CONCAT(DISTINCT t.Username SEPARATOR ',') AS tUsername
FROM mitglied u INNER JOIN
email e
ON u.ID = e.ID INNER JOIN
telephone t
ON u.ID = t.ID
WHERE u.Name REGEXP '$searchterm'
GROUP BY u.ID, u.name;
Notes:
I assume that mitglied is users.
Table aliases make the query easier to write and to read.
Qualified column names are recommended whenever you have multiple table references.

Duplicate GROUP_CONCAT when using JOIN

I'm creating a sort of geocache team building system and I'm having trouble with my query.
To collate and display the individuals against the teams I'm using GROUP_CONCAT, however when I try to include the locations (listed as markers) the individuals names are being duplicated based on the number of markers.
I have put together a SQL Fiddle to explain my workings.
Here is my query:
SELECT SQL_CALC_FOUND_ROWS
map_team.id AS team_id,
map_team.name,
GROUP_CONCAT(firstname, ' ', surname SEPARATOR ', ') AS full_name
FROM map_team
LEFT JOIN members
ON members.map_team=map_team.id
WHERE members.map_team IS NOT NULL
GROUP BY map_team.name
ORDER BY map_team.name ASC
Any advice would be appreciated.
GROUP_CONCAT( distinct ... ) will not give correct answers as the team member names in a team can be same. If you want to get it in a single query you can use:
SELECT SQL_CALC_FOUND_ROWS
map_team.id AS team_id,
map_team.name,
GROUP_CONCAT(firstname, ' ', surname SEPARATOR ', ') AS full_name,
(select count(*) from map_markers where team_id = map_team.id) AS total_markers,
(select count(*) from map_markers where team_id = map_team.id and status = 'completed') AS total_completed
FROM map_team
LEFT JOIN members
ON members.map_team=map_team.id
WHERE members.map_team IS NOT NULL
GROUP BY map_team.name
ORDER BY map_team.name ASC
If you don't like the idea of a subquery in select. You need to do it separately.
Use
GROUP_CONCAT(distinct firstname ...
use following query:
SELECT SQL_CALC_FOUND_ROWS
map_team.id AS team_id,
map_team.name,
GROUP_CONCAT(distinct firstname, ' ', surname SEPARATOR ', ') AS full_name,
count(*) AS total_markers,
SUM(IF(status = 'completed', 1, 0)) AS total_completed
FROM map_team
LEFT JOIN members
ON members.map_team=map_team.id
LEFT JOIN map_markers
ON map_markers.team_id=map_team.id
WHERE members.map_team IS NOT NULL
GROUP BY map_team.name
ORDER BY map_team.name ASC

Concat multiple results with left join not working

In my project I have a user table with regular information such as name, age, and the phone numbers are listed on another table with a relationship table to connect them.
Something like this.
TBL_User (name, dateofbirth, mail)
TBL_PhoneType (id, phonetype) //like, cellphone, home phone, etc.
TBL_PhoneNumber (id, phonetype, phonenuber) //lists muliple values for each user
TBL_PhoneRelation (userid, pnid)
I'm trying to make a selection to return the user information and a CONCAT version of the phone numbers, but the problem is the result that I get.
My first try is the GROUP_CONCAT, something like
SELECT us.name, us.dateofbirth, GROUP_CONCAT(' ', pt.phonetype, ' ', p.phonenumber)
FROM TBL_User AS us
LEFT JOIN TBL_PhoneRelation AS pr ON pr.userid = us.id
LEFT JOIN TBL_PhoneNumber AS p ON p.id = pr.pnid
The problem is that I get only one row and not all the values from the database and a regular CONCAT show only one phone number, and sub selection gives a error because I have more than 1 row in my result.
I'm trying something like this
User name | Phone number | E-mail
Adrian | Cellphone 11..., Home phone 22... | adrian...
Suzan | Cellphone 32..., Commercial phone 44... | sue...
I would do something like this:
select
U.Name,
group_concat(', ', T.PhoneType + ' ' + N.PhoneNumber)
U.Mail
from
TBL_user as U
left join
TBL_PhoneRelation AS R ON
R.UserID = U.ID
LEFT JOIN
TBL_PhoneNumber AS N ON
N.ID = R.PhoneID
left join
TBL_PhoneType as T on
T.ID = N.PhoneTypeID
group by
U.Name
select
U.Name,
group_concat(CONCAT(T.PhoneType + ' ' + N.PhoneNumber) SEPARATOR ','),
U.Mail
from
TBL_user as U
left join
TBL_PhoneRelation AS R ON R.UserID = U.ID
LEFT JOIN
TBL_PhoneNumber AS N ON N.ID = R.PhoneID
left join
TBL_PhoneType as T on T.ID = N.PhoneTypeID
group by
U.ID