MYSQL Selecting data from two different tables and no common variable name - mysql

I have two tables : Employee and Customer. Customer has customer ID, name, cust state, cust rep# and employee has employee first name, last name, employee phone number, employee number. Employee number = Cust Rep#.
I'm trying to extract employee first name, last name and employee phone number who serve customers that live in CA. This is what I had as a code but i get an error saying it returns more than one row
SELECT EMP_LNAME,
EMP_FNAME,
EMP_PHONE
FROM employee
WHERE EMP_NBR =
(SELECT CUST_REP
FROM customer
WHERE CUST_STATE='CA') ;

What's happening is that your inner query returns multiple rows, so change it to where EMP_NBR in to retrieve all matches.
The problem your query has is that it doesn't make sense to say = (a set which returns multiple rows), since it's unclear what exactly should be matched.

Use IN() instead of = when expecting a set of results to be returned in the subquery (rather than a single scalar result):
select EMP_LNAME,EMP_FNAME,EMP_PHONE
from employee
where EMP_NBR IN (
select CUST_REP from customer where CUST_STATE='CA'
);
Alternatively, you can use an INNER JOIN (or CROSS JOIN with a WHERE filter) to possibly do this more efficiently:
SELECT EMP_LNAME, EMP_FNAME, EMP_PHONE
FROM employee
INNER JOIN customer ON employee.EMP_NBR = customer.CUST_REP
WHERE customer.CUST_STATE = 'CA';

You don't need a nested query - better to write your query like this
select employee.emp_lname, employee.emp_fname, employee.emp_phone
from employee inner join customer
on employee.emp_nbr= customer.cust_rep
where customer.cust_state = 'CA'
You are getting that error message because there are several customers in California. This will not be a problem with the above query.

SELECT EMP_LNAME,
EMP_FNAME,
EMP_PHONE
FROM employee
WHERE EMP_NBR IN
(SELECT CUST_REP
FROM customer
WHERE CUST_STATE='CA') ;

Related

How to get distinct count of rows according to dates

Actually, i did counted distinct empid rows according to dates. But the problem is i get only one empid record of that specific dates.Please let me know how to get all empid records. Here is my sql query.
$sql = "
SELECT COUNT(DISTINCT subcount.empid) AS CountOf
, subcount.name
, subcount.date
, subcount.empid
, calendar.cdate
FROM subcount
, calendar
WHERE subcount.date = calendar.cdate
GROUP
BY subcount.date
";
Here is sql database.
For example, When you look at 2020-11-10 there are two empid with 10 and 7.
When i tried to get both records i get only empid 10 record or 7 record, though i need both record counts:
Here is the output:
Please help me on this.
I think what you are asking is to get list of employees with count of their submissions on a given date, this could show do it:
SELECT cnt.empid AS EmpId
, sc.Name
, cnt.`date` AS Timestamp
, cnt.CountOf AS SubmissionCount
FROM subcount AS sc
INNER JOIN
(
SELECT subcount.empid
subcount.`date`,
count(*) AS CountOf
FROM subcount
INNER JOIN calendar
ON subcount.`date` = calendar.cdate
GROUP BY
subcount.`date`, subcount.empid
) AS cnt
ON sc.empid == cnt.empid
It uses nested SELECT with GROUP BY to calculate count per employee (empid) and date (not only employee). Outer SELECT join nested SELECT to get subcount.Name piece of data which isn't retrieved in nested SELECT so it needs to be retrieved using outer SELECT.
GROUP BY ___ means result rows per ___. If you group by employee ID, you get one row per employee ID. If you want one row per employee ID and date, group by employee ID and date.
SELECT any_value(s.name), s.`date`, s.empid, c.cdate, count(*)
FROM subcount s
JOIN calendar c on c.cdate = s.`date`
GROUP BY s.`date`, s.empid
ORDER BY s.`date`, s.empid;
I expect a calendar table to have one row per date, so there is exactly one cdate for a result row. The name, however, can be different from row to row, so we must tell the DBMS, which to pick. With ANY_VALUE I tell it that I don't care which.

Get the first and last names of all employees who entered the project at the same time as at least one other employee

Question:
Get the first and last names of all employees who entered the project at the same time as at least one other employee.
I have four tables Employee, Department, Project, Works_on as shown in below.
I tried the query:
SELECT
emp_fname,
emp_lname
FROM employee a,
works_on b
WHERE a.empno=b.empno;
Please let me know what is wrong with what I am doing?
for this you need to use both Employee (emp_no,emp_fname,emp_lname) and Works_on (emp_no, Enter_date) relationship linked through emp_no on both tables.
in your query you just used Employee table which does not have connection with checking project submitted times.
You can use either of the below query to get the desired results. I have used partition by clause to group related data.
WITH QUERY1 AS (
SELECT EMP_NO,ENTER_DATE, COUNT(*) OVER (PARTITION BY ENTER_DATE ORDER BY EMP_NO ) "t" FROM works_on)
select t2.emp_fname, t2.emp_lname from query1 t1 inner join employee t2 on t1.emp_no=t2.emp_no where "t">1;
select emp_fname, emp_lname from employee where emp_no in (
SELECT EMP_NO FROM (
SELECT EMP_NO,ENTER_DATE, COUNT(*) OVER (PARTITION BY ENTER_DATE ORDER BY EMP_NO ) "t" FROM works_on
) query1 where query1."t">1);
First of all your query will return employee names who ever worked on any project, and better you would use INNER JOIN.
If I understand right; you want employee who work on the same project (let's say ProjectX) and again the employee who entered ProjectX on same time and also there must be at least 2 employee having the same time on ProjectX.
If I am correct with the above:
You need to group your data. For instance first group projects that have at least 2 same enter_date like
SELECT Project_no, Enter_date FROM Works_on having Count(emp_no)>=2
This will give you all projects and dates that have employee more or equal than 2. Now we can find employee that worked on these projects at these dates.
SELECT emp_fname, emp_lname FROM Employee INNER JOIN Works_on AS WO ON WO.emp_no=Employee.emp_no
INNER JOIN
(
SELECT Project_no, Enter_date FROM Works_on having Count(emp_no)>=2
) AS PWith2MoreEmployee
ON PWith2MoreEmployee.Project_no=WO.Project_no
AND
PWith2MoreEmployee.Enter_date=WO.Enter_date
I hope this will give you what you are looking for.

SQl query Multiple select statments in the same table under different conditions

So I have 3 tables that I want to perform some queries on but during that process I end up returning back to a table I already performed some functions on and it.
I first get the essn from one dependent table and search the employee table for a ssn matching it then i got the superssn and compare to the mgrssn in another table. The last step is to go back into the employee table and find the name of the person who has the same ssn of mgrssn.
The issue here is that once i get the matching superssn I can't access the other rows.
select lname, fname from
(select mgrssn from department) as d,
(select superssn, lname,fname,ssn from
(select essn from dependent where dependent_name ='joy') as de,
(select ssn,lname,fname,superssn from employee) as e
where essn =ssn) as s
where s.ssn = mgrssn
Should I look into doing joins instead?
You don't need the subqueries. Your query is a bit hard to follow (you don't have table aliases for all the columns), but I think this is what you are trying to do:
select lname, fname
from department d join
employee e
on e.ssn = d.mgrssn join
dependent dep
on dep.essn = e.ssn
where dep.dependent_name ='joy';
Simple rule: Never use commas in the from clause. Always use explicit join syntax.

FInd the names of customers are interested in every artist

I am looking for customer names of customers who have an interest in all artists.
I understand that in relational algebra, I can use the division operator, however I do not understand the SQL format in doing so.
I have these tables with columns:
customer (customerID, firstname, lastname)
artist (artistID)
customer_interest_in_artists (artistID, customerID)
How would I go about doing this?
You could do this using a simple MIN() construct:
SELECT c.firstname, c.lastname, MIN(ci.customerID IS NOT NULL) AS interest_all
FROM artist
LEFT JOIN customer_interest_in_artists ci USING (artistID)
LEFT JOIN customer c USING (customerID)
GROUP BY c.customerID
HAVING interest_all = 1
You could either:
Identify the customers for whom the number of rows in the customer_interest_in_artists table is equal to the number of rows in the artists table.
or
Identify the customers for whom there does not exist a row in the customer_interest_in_artists table for one or more artists.
The first option os probably easiest to implement, as you can already probably get the number of rows per customer (hint: join, count(*), and group) and compare the number per customer with the number of rows in artists -- hint: having count(*) = (a subquery)
for ORACLE, I use this...
but i don't think mine is the most elegant of all answers, anyway, here it is!
SELECT c.FIRSTNAME, c.LASTNAME, c.CUSTOMERID
FROM DTOOHEY.CUSTOMER c, DTOOHEY.CUSTOMER_ARTIST_INT cai
WHERE c.CUSTOMERID = cai.CUSTOMERID
AND c.CUSTOMERID IN
(SELECT cai.CUSTOMERID
FROM DTOOHEY.CUSTOMER_ARTIST_INT cai
GROUP BY cai.CUSTOMERID
HAVING COUNT (*) = (SELECT COUNT (*) FROM DTOOHEY.ARTIST)
)
GROUP BY c.FIRSTNAME, c.LASTNAME, c.CUSTOMERID;
based on my limited knowledge, the flow of command is:
1) I am trying to get the customer ID, first name and last name of customer
2) I am getting it from the 2 tables (cai and c)
3) trying to join the 2 tables to give me a single data set
4) where the c.customerid is to be gathered in...
this is where the magic begins!!!
5) select the customerID (the single CustomerID)
6) from this table cai
7) group the result based on customerID, this is what gives the single CustomerID Value that you need...
8) having COUNT (*) - having the count of customerID value, to that of equal of the number of count of artists in the dtoohey.artist table.
the main logic is that the number of artist in the artist table (which is 11), exist in the CUSTOMER_ARTIST_INT in the same quantity. As such, we can tally the result of count from the ARTIST Table into the CUSTOMER_ARTIST_INT table.
I think these will useful to you
SELECT a.customerID, c.artistID from customer a
join customer_interest_in_artists b on a.customerID = b. customerID
join artist c on c.artistID = b.artistID
Thank you.

Left outer join vs subquery to include departments with no employees

Lets say I have the following database model:
And the question is as follows:
List ALL department names and the total number of employees in the department. The total number of employees column should be renamed as "total_emps". Order the list from the department with the least number of employees to the most number of employees. Note: You need to include a department in the list even when the department does not currently have any employee assigned to it.
This was my attempt:
SELECT Department.deptname
(SELECT COUNT(*)
FROM Department
WHERE Department.empno = Employee.empno ) AS total_emps
FROM Department
I'm pretty sure my solution is not correct as it won't include departments with no employees. How do you use a left inner join to solve this problem?
The query as you were trying to write it is:
(table creates modified from shree.pat18's sqlfiddle to this sqlfiddle)
create table department (deptno int, deptname varchar(20));
insert into department values (1, 'a'),(2, 'b'),(3, 'c');
create table employee (empno int, deptno int);
insert into employee values (1,1),(2,1),(3,3);
SELECT d.deptname,
(SELECT COUNT(*)
FROM EMPLOYEE e
WHERE d.deptno = e.deptno ) AS total_emps
FROM DEPARTMENT d
ORDER BY total_emps ASC;
(You were counting from DEPARTMENT instead of EMPLOYEE and comparing empno instead of deptno. And you left out a comma.)
(You were asked for every department's name and employee count so this returns that. In practice we would include a presumably unique deptno if deptname was not unique.)
I'm pretty sure my solution is not correct as it won't include
departments with no employees.
Even your answer's version of the query (with the missing comma added) has an outer select that returns a count for every department no matter what the subselect returns. So I don't know why/how you thought it wouldn't.
If you want to use LEFT (OUTER) JOIN then the DEPARTMENT rows with no employees get extended by NULL. But COUNT of a column only counts non-NULL rows.
SELECT d.deptname, COUNT(e.empno) AS total_emps
FROM DEPARTMENT d
LEFT JOIN EMPLOYEE e
ON d.deptno = e.deptno
GROUP BY d.deptno
ORDER BY total_emps ASC;
(Nb the LEFT JOIN version uses more concepts: LEFT JOIN extending by NULL, GROUP BY, and COUNT's NULL behaviour for non-*.)
First off, it's a left outer join. Now, for your query, you want to join the 2 tables based on deptno, then also group by deptno (or deptname, since that is as likely to be unique) to ensure that any aggregation we do is done for each unique department in the table. Finally, the counting is done with the count function, leading to this query:
select d.deptname, count(e.empno) as total_emps
from department d
left join employee e on d.deptno = e.deptno
group by d.deptname
SQLFiddle
Note that since we want all records from department regardless of whether there are matching records in employee or not, department must appear at the left side of the join. We could have done the same thing using a right outer join by swapping the positions of the 2 tables in the join.