SQL if pivot table is empty = no result - mysql

I made this simple database on mysql and with data in my "Work" pivot table, I get the expected results with :
SELECT emp_name, dept_name
FROM Employee e
INNER JOIN Work w ON e.emp_id=w.emp_id
INNER JOIN Department d ON w.dept_id=d.dept_id;
+----------+-----------+
| emp_name | dept_name |
+----------+-----------+
| James | Sales |
| Jack | Marketing |
| James | Finance |
| Tom | Marketing |
+----------+-----------+
But now, if my pivot table is empty, I get NO RESULT as I would expect at least my emp_name list :
+----------+
| emp_name |
+----------+
| James |
| Jack |
| Henry |
| Tom |
+----------+
==> What should be the query for that ???
Thanks for help !
+--------+----------+--------+ Employee table
| emp_id | emp_name | salary |
+--------+----------+--------+
| 1 | James | 2000 |
| 2 | Jack | 4000 |
| 3 | Henry | 6000 |
| 4 | Tom | 8000 |
+--------+----------+--------+
+-------+-----------+ Department table
|dept_id| dept_name |
+-------+-----------+
| 1 | Sales |
| 2 | Marketing |
| 3 | Finance |
+-------+-----------+
+--------+---------+ Work table
| emp_id | dept_id |
+--------+---------+
| 1 | 1 |
| 2 | 2 |
| 1 | 3 |
| 4 | 2 |
+--------+---------+

Use a "left outer join":
SELECT emp_name, dept_name
FROM Employee e
LEFT JOIN Work w ON e.emp_id=w.emp_id
LEFT JOIN Department d ON w.dept_id=d.dept_id;

You seem to want left join:
SELECT emp_name, dept_name
FROM Employee e LEFT JOIN
Work w
ON e.emp_id = w.emp_id LEFT JOIN
Department d
ON w.dept_id = d.dept_id;
Note that this still returns two columns, but the second column is NULL.

In some situations, you need to fabricate a table for the columns.
I wanted a table with 24 columns, one per hour. In the output, I would put counts for actions grouped by day + hour. When there was no action in an hour, I wanted blank, not zero. (Blank stands out more than "0".)
To achieve that, I built a table with just 0..23.
SELECT ...
FROM seq_0_to_23 AS hours
LEFT JOIN the_data ON ...

Related

school work delivery list mysql

I have two tables:
Table students and table of school work delivered
Students table
+--------------------------+---------------------------------+
| id | name |
+--------------------------+---------------------------------+
| 1 | ADAM |
| 2 | BRIGITTE |
| 3 | ANNE |
+--------------------------+---------------------------------+
table student works
+---------------+-------------------------+------------------+
| id_works | works | id_student |
+---------------+-------------------------+------------------+
| 1 | airplane wing | 1 |
| 2 | volcano | 2 |
| 3 | law of gravity | 1 |
| 4 | airplane wing | 3 |
| 5 | law of gravity | 1 |
+-----------------------------------------+------------------+
How do I make a SELECT for work that returns the entire list of students, indicating that the work is delivered? (IMPORTANT: list of all students)
Example
LIST FOR WORK **airplane wing**
+--------------------------+---------------------------------+
| ADAM | X |
| BRIGITTE | |
| ANNE | X |
+--------------------------+--------------------- -----------+
I have tried it with LEF JOIN and IF, but it is not the list of all the students without repeating them.
SELECT
s.name ,
w.work,
w.resid_id,
if(w.work = 'airplane wing', 'X', '') as mark
FROM students s
LEFT JOIN works w
ON s.id = w.id_student
ORDER BY s.name ASC
This will give you a list of all students
And fields id_works and works will be null for those who didn't complete the work
SELECT s.name, w.id_works, w.works
FROM students s
LEFT JOIN works w
ON (w.id_student = s.id AND w.works = 'airplane wing')
ORDER BY s.name ASC

Why does Apache Drill select column with the same name of a different table

I have a PostgreSQL database linked to a Drill instance.
Whenever I am trying to join 2 tables which both have a column name and whenever I want to select this name Drill selects the wrong name column. What am I doing wrong?
Given the following 2 tables:
Department
| id | name |
|----|------|
| 1 | A |
| 2 | B |
Employee
| id | name | dept | salary |
|----|------|------|--------|
| 1 | U | 1 | 100 |
| 2 | V | 1 | 75 |
| 3 | W | 1 | 120 |
| 4 | X | 2 | 95 |
| 5 | Y | 2 | 140 |
| 6 | Z | 2 | 55 |
Running
select employee.name, employee.salary
from employee
inner join department on employee.dept = department.id
where department.name = 'A'
returns
| name | salary |
|------|--------|
| A | 100 |
| A | 75 |
| A | 120 |
Running
select dept.name, employee.salary
from employee
inner join department on employee.dept = department.id
where department.name = 'A'
returns
| name | salary |
|------|--------|
| null | 100 |
| null | 75 |
| null | 120 |
What does work, but seems very silly to me, is:
select dept.name, employee.salary
from employee
inner join (select id, name as deptname from department) as department on employee.dept = department.id
where department.deptname = 'A'
This seems to be because you use
select dept.name, [...]
But you have never assigned an alias for the table department (department AS dept). Hence
select department.name, [...]
should yield the value you are looking for.

Querying all data from a table joining ONLY the latest record from a junction table

I'm working with a database structure similar to this one: http://dev.mysql.com/doc/employee/en/sakila-structure.html
Table: employees
Table with information about each employee.
+---------+----------+
| emp_no* | emp_name |
+---------+----------+
| emp1 | John |
| emp2 | Mike |
| emp3 | Rob |
| emp4 | Kim |
+---------+----------+
Table: departments
Table with information about the departments of the company.
+----------+-----------+
| dept_no* | dept_name |
+----------+-----------+
| 1 | Dep 1 |
| 2 | Dep 2 |
| 3 | Dep 3 |
| 4 | Dep 4 |
| 5 | Dep 5 |
+----------+-----------+
JUNCTION TABLE: emp_dept
primary key: [ emp_no, from_date ]
Table to keep track of the departments where an employee had worked before or is working right now.
+---------+----------+------------+------------+
| emp_no* | dept_no | from_date* | to_date |
+---------+----------+------------+------------+
| emp1 | 1 | 2010-01-01 | 2010-12-31 |
| emp2 | 2 | 2010-01-01 | 2013-10-31 |
| emp1 | 4 | 2010-12-31 | 2012-06-14 |
| emp3 | 3 | 2010-01-01 | 2011-08-14 |
| emp4 | 1 | 2010-01-01 | 2014-11-14 |
| emp2 | 5 | 2013-10-31 | 2014-11-14 |
| emp1 | 3 | 2012-06-14 | 2014-11-17 |
| emp3 | 1 | 2011-08-14 | 2013-07-20 |
| emp3 | 4 | 2013-07-20 | 2014-11-14 |
+---------+----------+------------+------------+
THE EXPECTED TABLE:
¿How could I join only the latest record for each employee from the junction table (emp_dept) to my employee table and get a table like the one below?
+---------+----------+--------+
| emp_no* | emp_name | dep_no |
+---------+----------+--------+
| emp1 | John | 3 |
| emp2 | Mike | 5 |
| emp3 | Rob | 4 |
| emp4 | Kim | 1 |
+---------+----------+--------+
Assuming emp_dept.Emp_no is the relation between employees.Emp_no
Select * from
employees e
join emp_dept ed on e.emp_no = ed.emp_no
and from_date = (Select Max(from_date)
from emp_dept ed2 where ed2.emp_no = e.emp_no)
Create a query that only delivers the last Dept for each Employee, then add that to your main query in a JOIN or a CROSS APPLY
... tables with joins etc ...
CROSS APPLY
(
SELECT TOP 1 employee , dept_no FROM emp_dept
WHERE employee = !EMP FROM MAIN TABLE!
ORDER BY to_date DESC
) AS last_dept
where !EMP FROM MAIN TABLE! is your employee value from the tables before the CROSS APPLY
(Post your full query so far, for a more complete answer)
you can get the maximum date in a subquery and join with it.
looks like you have a typo in the emp_dept table entries, the emp_no is not matching with employees table.
In case a employee is currently working in deparment, does to_date will be NULL?
In such as case, you need to handle it in the sub query.
SELECT e.emp_no, e.emp_name, ED.dept_no
FROM
(
SELECT emp_no, max(to_date) as maxDate
FROM emp_dept
group by emp_no)T
JOIN employee e
ON T.emp_no = e.emp_no
JOIN emp_dept ED
on T.maxDate = ED.t_date
AND ED.emp_no = T.emp_no

mysql select count from multiple tables

If I have two tables job, employee.
I need to select all from job and append employee count for each job.
Supposed Result
job table
+-------------+-------------+
| id | name |
+-------------+-------------+
| 1 | Teacher |
+-------------+-------------+
| 2 | Engineer |
+-------------+-------------+
| 3 | Programmer |
+-------------+-------------+
employee table
+-------------+-------------+-------------+
| id | name | job_id |
+-------------+-------------+-------------+
| 1 | employee N | 1 |
+-------------+-------------+-------------+
| 2 | employee N | 2 |
+-------------+-------------+-------------+
| 3 | employee N | 3 |
+-------------+-------------+-------------+
| 4 | employee N | 1 |
+-------------+-------------+-------------+
| 5 | employee N | 3 |
+-------------+-------------+-------------+
| 6 | employee N | 1 |
+-------------+-------------+-------------+
I need to select all from job and append employee count for each job.
Supposed Result
Result table
+-------------+-------------+--------------+
| id | name |employee count|
+-------------+-------------+--------------+
| 1 | Teacher | 3 |
+-------------+-------------+--------------+
| 2 | Engineer | 1 |
+-------------+-------------+--------------+
| 3 | Programmer | 2 |
+-------------+-------------+--------------+
I like to use left join : )
SELECT job.id, job.name, count( * ) AS 'employee count'
FROM job
LEFT JOIN employee
ON job.id = employee.job_id
GROUP BY job.id
You want to use INNER JOIN to join the tables, then GROUP BY to group on the job id. Finally use COUNT() to get a count of each group
SELECT job.id, job.name, count(*) AS employee_count
FROM job
INNER JOIN employee
ON job.id = employee.job_id
GROUP BY job.id
You can see it live here http://sqlfiddle.com/#!2/9d59c1/1

How can I join two tables, keeping rows that do not meet the JOIN condition?

ticket
+----------+--------+
| ticketID | assign |
+----------+--------+
| 1015 | NULL |
| 1020 | James |
| 1021 | Nick |
+----------+--------+
staffinfo
+---------+-------+
| staffID | staff |
+---------+-------+
| 1 | Jane |
| 2 | James |
| 3 | Nick |
| 4 | Cole |
+---------+-------+
SELECT staff,COUNT(*) as count FROM staffinfo,ticket
WHERE ticket.assign = staffinfo.staff
GROUP BY staff
result:
+-------+-------+
| staff | count |
+-------+-------+
| James | 1 |
| Nick | 1 |
+-------+-------+
Works fine, but infact i need smthing like:
+-------+-------+
| staff | count |
+-------+-------+
| James | 1 |
| Nick | 1 |
| Jane | 0 |
| Cole | 0 |
+-------+-------+
COUNT doesnt count records that arent in the table, and since i just started learning SQL, i wanna ask if theres a way to count as the above result?
you should be using LEFT JOIN
SELECT a.staff, COUNT(b.assign) as count
FROM staffinfo a
LEFT JOIN ticket b
ON b.assign = a.staff
GROUP BY a.staff
SQLFiddle Demo
To fully gain knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
Use LEFT JOIN
The LEFT JOIN keyword returns all rows from the left table (table_name1), even if there are no matches in the right table (table_name2).
SELECT staffinfo.staff, count(ticket.assign)
FROM staffinfo
LEFT JOIN ticket
ON ticket.assign =staffinfo.staff
GROUP BY staffinfo.staff
The LEFT JOIN keyword returns all the rows from the left table (staffinfo), even if there are no matches in the right table (ticket).