I have two tables in MySQL.
First table is EMPLOYEES, it contain such columns as LASTNAME, NAME, MIDDLENAME, BIRHDATE and others about employees.
Second table is PROJECTS. It has among other things column STAFF.
STAFF has rows like
lastname1 name1, middlename1; lastname2 name2, middlename2.....
I need to get people from EMPLOYEES who are in the STAFF.
query
SELECT LASTNAME, NAME, MIDDENAME from EMPLOYEES where
CONCAT('%', LASTNAME, ' ', NAME, ' ',MIDDENAME, '%')
like (SELECT STAFF FROM PROJECTS)
doesn't work because LIKE must have one substring from 2nd query
and query
SELECT LASTNAME, NAME, MIDDENAME from EMPLOYEES where
CONCAT('%', LASTNAME, ' ', NAME, ' ',MIDDENAME, '%')
IN (SELECT STAFF FROM PROJECTS)
doesn't work too because for IN need full matching
any ideas?
That's what happens when you have delimited string like that in table which is against normalization. First consider normalizing your table. For now, you can perform a JOIN probably like below but if STAFF column has data in exact in format else matching will not occur.
SELECT e.LASTNAME, e.NAME, e.MIDDENAME
FROM EMPLOYEES e
JOIN PROJECTS p
ON CONCAT(e.LASTNAME, ' ', e.NAME, ' ', e.MIDDENAME) = p.STAFF;
You can as well use FIND_IN_SET() function like below but again consider changing your DB design first and Normalize your table(s)
SELECT LASTNAME,
NAME,
MIDDENAME
FROM (
SELECT LASTNAME, NAME,
MIDDENAME,
CONCAT(e.LASTNAME, ' ', e.NAME, ' ', e.MIDDENAME) as Full_Name
FROM EMPLOYEES) e
JOIN PROJECTS p
ON FIND_IN_SET(Full_Name, p.STAFF) > 0;
Related
I am super new to SQL, but hoping for some input on the below. In this assignment, we aren't supposed to use PK or FK so everything is cross referenced. I have an EMPLOYEE table with a column for Manager ID as the Employee ID, and a CityID which is referenced to the City table which includes the ID and Name.
I need to pull up the Employee's name, employee's city, manager name and the managers city, the issue I am having is, one the manager has a NULL value in the City, so it is not producing all of the possible results. If there is a NULL value in any of the columns, I want it to show NULL.
Any idea what I could add to allow for NULL values?
Here is the query so far:
SELECT
CONCAT(e.FirstName, ' ', e.LastName) AS 'EmployeeName', c.CityName AS 'EmployeeCity',
CONCAT(m.FirstName, ' ', m.LastName) AS 'ManagerName', ci.CityName AS 'ManagerCity'
FROM
EMPLOYEE e
JOIN
EMPLOYEE m
ON e.ManagerID = m.EmployeeID
JOIN
CITY c
ON e.CityID = c.CityID
JOIN
CITY ci
ON m.CityID = ci.CityID;
JOIN returns all rows from tables where the key record of one table is equal to the key records of another table
INNER JOIN returns only matching tuples/rows if there is a much on the right of he compared tables.
While LEFT OUTER JOIN returns all matching tuples/rows from both compared tables.
I recommend that you use LEFT OUTER JOIN in your case.
In your case, just use concat_ws():
SELECT CONCAT_WS(' ', e.FirstName, e.LastName) AS EmployeeName,
c.CityName AS EmployeeCity,
CONCAT_WS(' ', m.FirstName, m.LastName) AS ManagerName,
ci.CityName AS ManagerCity
CONCAT_WS() ignores NULL values. And as a bonus, won't include the space.
Note: Only use single quotes for string and date constants. Do not use them for column names.
#casscode you need to use a LEFT JOIN in your query, like this:
SELECT CONCAT(e.FirstName, ' ', e.LastName) AS 'EmployeeName',
c.CityName AS 'EmployeeCity',
CONCAT(m.FirstName, ' ', m.LastName) AS 'ManagerName',
ci.CityName AS 'ManagerCity'
FROM EMPLOYEE e
JOIN EMPLOYEE m ON e.ManagerId = m.EmployeeId
LEFT JOIN CITY c ON e.CityId = c.CityId
LEFT JOIN CITY ci ON m.CityId = ci.CityId;
Thus, the script displays the values, but duplicates them, many values with the same email and date. You need to get unique values, for example, there may be the same emails, but with a different date. But not the same emails with the same date.
DISTINCT after SELECT does not work, as well as applying it before each field.
group by and order by too, they cannot add more than two fields. When I accept group by email, it displays all the unique values, but does not display the values that are also needed when two identical emails, but different dates, it displays stupidly one email and that's it.
What to do help.
SELECT concat(last_name, ' ', first_name, ' ', middle_name) as 'ФИО',
email,
phone,
created_at,
total,
color
FROM user
INNER JOIN `user` ON `order`.user_id = `user`.id
INNER JOIN `color` ON `user`.color_id = `color`.id
You need to use the keyword DISTINCT after the SELECT.
Example:
SELECT DISTINCT concat(last_name, ' ', first_name, ' ', middle_name) as 'ФИО',
email,
phone,
created_at,
total,
color
FROM user
You have order the results by combing fields from the three tables:
SELECT concat(last_name, ' ', first_name, ' ', middle_name) as 'ФИО',
email,
phone,
created_at,
total,
color,
o.PRIMARY_KEY_HERE,
c.id
FROM user AS u
INNER JOIN `order` AS o ON o.user_id = u.id
INNER JOIN `color` AS c ON c.id = u.color_id
ORDER BY u.email, o.PRIMARY_KEY_HERE, c.id
Note
The query has been refactored to satisfy the ORDER BY clause.
create list of all writer and the count of books they have written .
*Create one new column as writers name adding the first and last name from the writers table
*Get the count of books they have written in a new coulmns as number of books written
*Finally List to be ordered by Writers name , title and launch date
Im have created a simple question here as im trying to build something on similar ground:
Books:
Writers:
Expected Result:
SELECT *
FROM books b
INNER JOIN (
SELECT CONCAT(first_name,' ', last_name) AS author,COUNT(*) As booksWritten
FROM books
GROUP BY CONCAT(first_name,' ', last_name) c
ON CONCAT(b.first_name,' ', b.last_name=c.author
Is this what you want?
In MySQL 8.x you can use a window function. For example:
select
b.book_id,
b.title,
b.launch_date,
concat(w.first_name, ' ', w.last_name) as writers_name,
count(*) over(partition by w.first_name, w.last_name) as book_count
from book_table b
join write_table w on w.book_id = b.book_id
order by b.launch_date
I need to combine two tables.
The first table is People(SSN PRIMARY KEY, fname, lname).
The other table is Cities(name, cityID), where name = "fname lname" i.e. 2 columns of People concatenated with a space between. One person may have multiple cities associated with them, and a city may have more than one person (many - many).
I want to combine the two into a table PeopleCities(SSN, cityID). If no person is found for a city, I need SSN to be 0 for that cityID. My experience is mostly with sqlite rather than mySQL, so I'm not very confident in my query.
Here is my query:
SELECT ISNULL(People.SSN, 0), Cities.cityID
FROM People
FULL OUTER JOIN Cities
ON (Cities.name = CONCAT_WS(" ", People.fname, " ", People.lname) FROM People);
You can use UNION ALL, first to get the people/city pairs that match and then to get the non-matches:
select p.ssn, coalesce(c.cityid, 0)
from people p left join
cities c
on c.name = concat_ws(' ', p.name, p.lname)
union all
select distinct 0, c.cityid
from cities c
where not exists (select 1 from people p where c.name = concat_ws(' ', p.name, p.lname);
Banging my head on this one and not sure how to resolve. I need to return 1 row per teamcode from the teams tables (distinct values) that includes user information.
Table users can have multiple values bases on the team code but I need it to only return 1 (any one, it doesn't matter which). I've tried:
SELECT a.teamcode, a.area, c.uniqid, c.fullname, c.email
FROM teams a
LEFT JOIN
(SELECT uniqid, CONCAT(first_name, ' ', last_name ) AS fullname, email, teamcode from users LIMIT 1) c
on a.teamcode = c.teamcode
WHERE a.area= 'ZF15'
Ive also tried max:
SELECT a.teamcode, a.area, c.uniqid, c.fullname, c.email
FROM teams a
LEFT JOIN
(SELECT max(uniqid) as uniqid, CONCAT(first_name, ' ', last_name ) AS fullname, email, teamcode from users) c
on a.teamcode = c.teamcode
WHERE a.area= 'ZF15'
But the sub query returns null values from the users table. However, when I remove limit and max, I get the users table values but I get multiple rows per team code. Any ideas?
I think this should work, joining users on itself on the max(uniqid) per team:
SELECT a.teamcode, a.area,
c.uniqid, CONCAT(c.first_name, ' ', c.last_name ) AS fullname, c.email
FROM teams a
LEFT JOIN (
SELECT MAX(uniqid) maxuniqid, teamcode
FROM users
GROUP BY teamcode
) u on a.teamcode = u.teamcode
LEFT JOIN users c on c.teamcode = u.teamcode
AND c.uniqid = u.maxuniqid
WHERE a.area= 'ZF15'
This gets the max(uniqid) from the users table, grouped by the teamcode (1 for each team). Then joins back to the users table to get the name and email for that user.