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.
Related
I have two columns first_name and last_name.
To search for a row against passed search text I am using iLik query.
SELECT * FROM t1 WHERE t.first_name ILIKE %John% or t.last_name ILIKE %John%;
Above works.
But I want to search for full name, both on first_name and last_name. It does not return the row.
SELECT * FROM t1 WHERE t.first_name ILIKE %John Doe% or t.last_name ILIKE %John Doe%;
Above empty result.
How can I make this to search on both the columns matching against sub parts of the search text?
I presume that John & Doe are in the two separate columns, so 'John' in t.first_name & 'Doe' in t.last_name. Your bottom query is looking for the full name in just one of the columns. If the names have been split out between the two columns then the full name will not appear in one column. I am pressuming that the columns will also just contain that first and last name, so the ILIKE will not be needed and you can just run an equals to,In order to achieve what you need, please run the following:
Equals version - SELECT * FROM t1 WHERE t.first_name = 'John' AND t.last_name = 'Doe';
Wildcard version - SELECT * FROM t1 WHERE t.first_name ILIKE %John% AND t.last_name ILIKE %Doe%;
Let me know how you get on.
I tried using CONCAT function and it's working,
SELECT *
FROM t1
WHERE CONCAT(t.first_name, ' ', t.last_name) ILIKE '%John Doe%';
I have two tables:
Customers phones : contains first name, last name and phone:
phones
Customers Email: contains full name (first name + last name) and email.
email
I have to join them in order to get this result:
result
My query:
select *, email
from customersPhones
join customersEmail on ??
How can I do it?
This will work for MySQL, similar solutions will work for other SQL variants
SELECT firstname, lastname, phone, email
FROM phones
JOIN email ON
email.name = CONCAT(phones.firstname, ' ', phones.lastname)
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
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
I have a table of games, like this:
ID | game name
1 legend of zelda
2 metal gear solid
3 resident evil
And another table of users owning those games, like this:
ID | User ID | Game ID
1 510 2
2 879 2
3 213 3
I need to make a list of games with a number of users owning them. From the above, the result would be:
legend of zelda (0 users)
metal gear solid (2 users)
resident evil (1 user)
How do I do the above using only 1 SQL query?
SELECT g."game name" AS name, COUNT(u.ID) AS users
FROM games AS g LEFT JOIN game_users AS u
ON g.ID = u."Game ID"
GROUP BY g."game name"
I've used SQL standard double quotes around the space-containing delimited identifiers since you didn't identify which sub-species of SQL you are using.
This gives you two columns of output - the game name and a simple count. If you want the decorative '(0 users)' and '(1 user)' notations, then you are into some more serious pain unless your DBMS provides a convenient function to handle the correct inflections for different numbers of an object in your language (apparently English - but the rules vary by language).
Doing the simple-minded computerese:
SELECT TRIM(r.name) || ' (' || r.users || ' users)'
FROM (SELECT g."game name" AS name, COUNT(u.ID) AS users
FROM games AS g LEFT JOIN game_users AS u
ON g.ID = u."Game ID"
GROUP BY g."game name") AS r
Or, slightly more sophisticated (but English-only):
SELECT TRIM(r.name) || ' (' || r.users || ' user' ||
CASE r.users WHEN 1 THEN '' ELSE 's' END || ')'
FROM (SELECT g."game name" AS name, COUNT(u.ID) AS users
FROM games AS g LEFT JOIN game_users AS u
ON g.ID = u."Game ID"
GROUP BY g."game name") AS r
However, in my book, SQL is for the data; presentation is best done in the application. Therefore, I'd probably use the first query.
Join them, group on game id, and select the count(*) of rows, or count(distinct users). If one guy owns the game twice, and you want that to count as only one owner, distinct users.
SELECT game.name, count(*)
FROM games
JOIN ownershipInfo
ON games.id = ownershipInfo.id
GROUP BY game.name --missing from original answer, oops
That will give you the number of rows.
Since you want to include where there are zero, do "LEFT JOIN" instead of plain join. If you want the count not of rows but distinct owners:
SELECT game.name, count(distinct ownershipInfo.ownerID)
FROM games
JOIN ownershipInfo
ON games.id = ownershipInfo.id
GROUP BY game.name --missing from original answer, oops
As jonathon points out you need a GROUP BY to get the aggregate information. And here I just took the expedient of grouping by name - usually you'd group by the game's ID, and do something more like:
SELECT max(game.id), count(distinct ownershipInfo.ownerID)
FROM games
LEFT JOIN ownershipInfo
ON games.id = ownershipInfo.id
GROUP BY games.id
That way if two games have the same name, you'd get a row for both (of course it wouldn't be self explanatory but maybe you'd also have MAX(publisher) or something to clarify which one was which)
SELECT g."game name" AS name, COUNT(*) AS users
FROM games AS g
INNER JOIN game_users AS u
ON g.ID = u."Game ID"
GROUP
BY g."game name"
UNION
SELECT g."game name" AS name, 0 AS users
FROM games AS g
WHERE NOT EXISTS (
SELECT *
FROM game_users AS u
WHERE g.ID = u."Game ID"
);