I am trying to write a simple query that will display all projects and their total number of team members, sorted alphabetically by project. If a project does not have assigned team members, that project should still be included in the output.
CREATE TABLE Project ( ID INT IDENTITY(1,1), ProjectName VARCHAR(50), DueDate
DATE)
CREATE TABLE Employee ( ID INT IDENTITY(1,1), EmployeeName VARCHAR(50) )
CREATE TABLE ProjectAssignment ( ID INT IDENTITY(1,1), ProjectID INT,
EmployeeID INT)
INSERT INTO Project VALUES ('Alpha', '1/1/2040'), ('Bravo', '3/1/2030'),
('Charlie', '2/1/2017'), ('Delta', '4/1/2017')
INSERT INTO Employee VALUES ('John'), ('Beth'), ('Tom'), ('Kim'), ('Jack')
INSERT INTO ProjectAssignment VALUES (1, 1), (1, 2), (2, 2), (2, 3), (3,
3), (3, 4), (1, 3)
--TABLE Project:
ID ProjectName DueDate
1 Alpha 2040-01-01
2 Bravo 2030-03-01
3 Charlie 2017-02-01
4 Delta 2017-04-01
--TABLE Employee:
ID EmployeeName
1 John
2 Beth
3 Tom
4 Kim
5 Jack
--TABLE ProjectAssignment:
ID ProjectID EmployeeID
1 1 1
2 1 2
3 2 2
4 2 3
5 3 3
6 3 4
7 1 3
Here is my wrong query:
SELECT n.ProjectName, Count(t.ProjectID) as NumMembers
FROM Project p
LEFT JOIN ProjectAssignment t ON p.EmployeeID = t.EmployeeID
LEFT JOIN employee e ON e.ProjectID = t.ProjectID
GROUP BY n.Project
ORDER BY n.Project
Desired Result:
| ProjectName | NumMembers |
+-------------+-------------+
| Alpha | 3 |
| Bravo | 2 |
| Charlie | 2 |
| Delta | null |
Please try this Mysql query. This will resolve your issue. We dont' require employee table join. If you are not taking any data from employee table then don't add employee table in join.
SELECT
p.name AS ProjectName,
Count( t.employeeID ) AS NumMembers
FROM
Project p
LEFT JOIN ProjectAssignment t ON p.id = t.projectID
GROUP BY
p.name
Output:
Project name NumMembers
Alpha 3
Bravo 2
Charlie 2
Delta 0
Few things
LEFT JOIN ProjectAssignment t ON p.EmployeeID = t.EmployeeID
is wrong as you can see p.EmployeeID do not exists on table Project
your join to employee is not needed at all
also finally i do not know how your fields names are. you post Name in sample data and projectName is used in your query and ddl (changed to your DDL instead of your query)
SELECT p.ProjectName, Count(DISTINCT pa.EmployeeID) as NumMembers
FROM Project p
LEFT JOIN ProjectAssignment pa ON p.ID = pa.ProjectID
GROUP BY p.ID, p.ProjectName
ORDER BY p.ProjectName
http://sqlfiddle.com/#!18/36df5/1
SELECT n.ProjectName, Count(t.ProjectID) as NumMembers FROM Project n LEFT JOIN ProjectAssignment t ON n.id = t.ProjectID GROUP BY t.ProjectID ORDER BY n.ProjectName
run this query
Just use this ( it seems join conditions are mixed ):
SELECT p.ProjectName, Count(t.ProjectID) as NumMembers
FROM Project p
LEFT JOIN ProjectAssignment t ON p.ID = t.ProjectID
LEFT JOIN employee e ON t.EmployeeID = e.ID
GROUP BY p.ProjectName
ORDER BY p.ProjectName;
ProjectName NumMembers
Alpha 3
Bravo 2
Charlie 2
Delta 0
SQL Fiddle Demo
Related
I'm currently new to queries and below I have a query that I have made
QUERY:
select TITLE_ID, TITLE,NAME, JOB_CATEGORY AS ROLE
FROM MOVIES
NATURAL JOIN NEW_NAMES
WHERE JOB_CATEGORY = 'writer'
OR JOB_CATEGORY = 'director'
ORDER BY TITLE_ID ASC;
Which Displays:
TITLE_ID | TITLE | NAME | ROLE |
753595 | 2F2F | ROB | WRITER |
753595 | 2F2F | YAS | DIRECTOR|
However I would like it to display in this format below:
TITLE_ID | TITLE | WRITER | DIRECTOR|
753595 | 2F2F | ROB | YAS |
You join your NEW_NAMES table in twice. Once for director, once for writer. When you join a table more than once it's necessary that you give the table an Alias, here we use writer and director.
select TITLE_ID, TITLE,writer.NAME as writer_name, director.NAME as director_name
FROM MOVIES
LEFT OUTER JOIN NEW_NAMES as writer
ON MOVIES.TITLE_ID = writer.TITLE_ID
AND writer.JOB_CATEGORY = 'writer'
LEFT OUTER JOIN NEW_NAMES as director
ON MOVIES.TITLE_ID = director.TITLE_ID
AND director.JOB_CATEGORY = 'director'
ORDER BY TITLE_ID ASC;
I've made some assumptions in those ON clauses about which columns in your tables you are joining on. You may need to edit that.
According to error message you got, it is about Oracle, not MySQL.
Anyway, such a (classic?) principle should work: aggregate!
SQL> with
2 -- sample data
3 movies (title_id, title_name) as
4 (select 753595, '2F2F' from dual union all
5 select 123456, '1Z1Z' from dual
6 ),
7 new_names (title_id, job_category, name) as
8 (select 753595, 'writer', 'ROB' from dual union all
9 select 753595, 'director', 'YAS' from dual
10 )
11 -- query you need
12 select m.title_id,
13 m.title_name,
14 max(case when n.job_category = 'writer' then n.name end) as writer,
15 max(case when n.job_category = 'director' then n.name end) as director
16 from movies m left join new_names n on m.title_id = n.title_id
17 group by m.title_id, m.title_name
18 order by m.title_id;
TITLE_ID TITL WRI DIR
---------- ---- --- ---
123456 1Z1Z
753595 2F2F ROB YAS
SQL>
I want to Join to table. the condition is I want to only join those rows which have only one row to match. eg.
books:
id | name | price
1 | book1 | 19
2 | book2 | 19
3 | book3 | 30
price_offer:
id | offer | price
1 | offer1 | 19
2 | offer2 | 30
so now if I do select query on these table:
SELECT * FROM price_offer
JOIN books ON price_offer.price = books.price
I only want to join book with id 3 as it have only one match with price_offer table.
You could use a self join for books table to pick a book with only single match
select po.*, b1.*
from price_offer po
join books b1 on po.price = b1.price
join (
select price,max(id) id
from books
group by price
having count(*) = 1
) b2 on b1.id = b2.id
Demo
Try following query:
Sample data:
create table books(id int, name varchar(10), price int);
insert into books values
(1, 'book1', 19),
(2, 'book2', 19),
(3, 'book3', 30);
create table price_offer(id int, offer varchar(10), price int);
insert into price_offer values
(1, 'offer1', 19),
(2, 'offer2', 30);
Query:
select max(b.id)
from price_offer p
left join books b on b.price = p.price
where p.id is not null
group by b.price
having count(*) = 1;
If you want to avoid nesting queries where you have to use self-joins, you can use window-functions of MySQL 8.0.11, which are exactly for cases like this
How to get the TeamCount and TeamLead Name currectly
Teams | TeamCount | TeamLead Name
-------------------------------------
| Team1 | 2 | NULL
| Team2 | 2 | NULL
| Team1 | 1 | Prashanth
Some times Team may or may not have the team lead.
So we just have to show the TeamLead name as null,
if team lead is not found for the team
I need some help to get the out as below
Teams | TeamCount | TeamLead Name
---------------------------------
Team1 | 3 | Prashanth
Team2 | 2 | NULL
Here you are:
MySQL:
select team as teamId, sum(teamcount) as teamcount,
(select teamleadname from teams
where teamId = teams.team and teamleadname is not null
limit 1) as teamleadname
from teams
group by team
http://sqlfiddle.com/#!9/5889d/39
SQl Server:
declare #teams TABLE(Team varchar(20), TeamCount int, TeamLeadName varchar(20));
INSERT INTO #teams
VALUES
('Team1', 2, null),
('Team2', 2, null),
('Team1', 1, 'Prashanth')
select l.Team, l.TeamCount, r.TeamLeadName
from
(select Team , sum(TeamCount) as TeamCount from #teams group by Team) as l
left outer join
(select Team, TeamLeadName
from
(select Team, TeamLeadName, row_number() over(partition by Team order by TeamLeadName desc) as roworder
from #teams) as o where o.roworder = 1
) as r
on l.Team = r.Team
Hope this help.
...and here you go!
create table test2 as
select distinct c.teams,sum(c.TeamCount) as SUM,c.TeamName
from
(select a.Teams,a.TeamCount,b.TeamName from team as a
left outer join
(select * from team where TeamName ne "") as b
on a.Teams = B.Teams) as c
group by c.Teams;
You should try to develop these solutions by working from the inside out and build the query in steps
You can do this with a LEFT OUTER join between Team and TeamMembers, and including the IsLead into the join criterion, before grouping by the Team name - this will exclude non-leads:
SELECT T.Name, MIN(TM.TName) AS Lead
FROM Teams T
LEFT OUTER JOIN TeamMembers TM
ON TM.TeamId = T.Id AND TM.IsLead = 1
GROUP BY T.Name;
SqlFiddle here
The TeamCount doesn't seem to make sense here - if you can elaborate on how you intend deriving it, perhaps we can help here
PS : You've tagged both MySql and Oracle - don't do this please.
Let's say i've got this database:
book
| idBook | name |
|--------|----------|
| 1 |Book#1 |
category
| idCateg| category |
|--------|----------|
| 1 |Adventures|
| 2 |Science F.|
book_categ
| id | idBook | idCateg | DATA |
|--------|--------|----------|--------|
| 1 | 1 | 1 | (null) |
| 2 | 1 | 2 | (null) |
I'm trying to select only the books which are in category 1 AND category 2 something like this
SELECT book.* FROM book,book_categ
WHERE book_categ.idCateg = 1 AND book_categ.idCateg = 2
Obviously, this giving 0 results becouse each row has only one idCateg it does work width OR but the results are not what I need. I've also tried to use a join, but I just can't get the results I expect.
Here it's the SQLFiddle of my current project, with my current DB, the data at the begining is just a sample. SQLFiddle
Any help will be really appreciated.
Solution using EXISTS:
select *
from book b
where exists (select 'x'
from book_categ x
where x.idbook = b.idbook
and x.idcateg = 1)
and exists (select 'x'
from book_categ x
where x.idbook = b.idbook
and x.idcateg = 2)
Solution using join with an inline view:
select *
from book b
join (select idbook
from book_categ
where idcateg in (1, 2)
group by idbook
having count(*) = 2) x
on b.idbook = x.idbook
You could try using ALL instead of IN (if you only want values that match all criteria to be returned):
SELECT book.*
FROM book, book_categ
WHERE book_categ.idCateg = ALL(1 , 2)
One way to get the result is to do join to the book_categ table twice, something like
SELECT b.*
FROM book b
JOIN book_categ c1
ON c1.book_id = b.id
AND c1.idCateg = 1
JOIN book_categ c2
ON c2.book_id = b.id
AND c2.idCateg = 2
This assumes that (book_id, idCateg) is constrained to be unique in the book_categ table. If it isn't unique, then this query can return duplicate rows. Adding a GROUP BY clause or the DISTINCT keyword will eliminate any generated duplicates.
There are several other queries that can get generate the same result.
For example, another approach to finding book_id that are in two categories is to get all the rows with idCateg values of 1 or 2, and then GROUP BY book_id and get a count of DISTINCT values...
SELECT b.*
FROM book b
JOIN ( SELECT d.book_id
FROM book_categ d
WHERE d.idCateg IN (1,2)
GROUP BY d.book_id
HAVING COUNT(DISTINCT d.idCateg) = 2
) c
ON c.book_id = b.id
I have one table called Employee that contains the following information like
ID Name Skills
1 xyz java,php,dotnet
2 abc ruby,java,python
Skills column saves comma seprated values. it could be one or more.
I want to design a query based on OR operate.When user search java, Database displays two employees likes xyz, abc.
I have tried this query but no result comes out:
SELECT m
FROM Employee m
Where m.Skills LIKE '%JAVA% MS PAINT%'
Any Suggestion?
Ideally you should not store the data in a comma-separated list. You should create a join table between the employees and the skills:
CREATE TABLE employees (`e_id` int, `e_name` varchar(3));
INSERT INTO employees (`e_id`, `e_name`)
VALUES
(1, 'xyz'),
(2, 'abc');
CREATE TABLE skills (`s_id` int, `s_name` varchar(6));
INSERT INTO skills (`s_id`, `s_name`)
VALUES
(1, 'java'),
(2, 'php'),
(3, 'dotnet'),
(4, 'ruby'),
(5, 'python');
CREATE TABLE employees_skills (`e_d` int, `s_id` int);
INSERT INTO employees_skills
(`e_d`, `s_id`)
VALUES
(1, 1),
(1, 2),
(1, 3),
(2, 4),
(2, 1),
(2, 5);
Then when you want to select from the tables you will use:
select *
from employees e
inner join employees_skills es
on e.e_id = es.e_id
inner join skills s
on es.s_is = s.s_id
where s.s_name in ('java', 'ruby')
Or you can use the OR clause:
select *
from employees e
inner join employees_skills es
on e.e_id = es.e_id
inner join skills s
on es.s_is = s.s_id
where s.s_name = 'java'
or s.s_name = 'ruby'
use like not good solution. Full scan and slow query.
Create new table with catalog of skills.
Create table user_skills
You should set up your tables like this:
Employee:
ID | Name
---+------
1 | xyz
2 | abc
Skill:
ID | Name
---+------
1 | java
2 | php
3 | dotnet
4 | ruby
5 | python
EmployeeSkills:
ID | EmployeeID | SkillID
---+------------+----------
1 | 1 | 1
2 | 1 | 2
3 | 1 | 3
4 | 2 | 4
5 | 2 | 1
6 | 2 | 5
the query to find employees with skills in java would look like this
SELECT
E.Name
FROM
Employee AS E
INNER JOIN
EmployeeSkill AS ES
ON
ES.EmployeeID = E.ID
INNER JOIN
Skill AS S
ON
ES.SkillID = S.ID
WHERE
S.Name = 'java'
select name from table where skill like '%java%' should do