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
Related
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 ...
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.
I'm trying to select orders, which are send at least two times with the same addressId to a customer.
This is my table structure:
Customer Table:
+------------+-----------+
| customerId | addressId |
+------------+-----------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
+------------+-----------+
Relation for Addresses to Orders
+---------+-----------+
| orderId | addressId |
+---------+-----------+
| 1 | 1 |
| 2 | 2 |
| 3 | 2 |
| 4 | 3 |
| 5 | 4 |
| 6 | 4 |
+---------+-----------+
Order Table
+----+------------+-------+
| id | orderEntry | total |
+----+------------+-------+
| 1 | timestamp | 4711 |
| 2 | timestamp | 0815 |
| 3 | timestamp | 1337 |
+----+------------+-------+
Now I want a output like this:
+------------+---------+-----------+
| customerId | orderId | addressId |
+------------+---------+-----------+
| 2 | 2 | 2 |
| 2 | 3 | 2 |
| 4 | 5 | 4 |
| 4 | 6 | 4 |
+------------+---------+-----------+
I've tried to get the right result with these Query, but I think I can't count the addresses this way.
SELECT C.`customerId`, AO.`orderId`, AO`addressId`
FROM customer AS C
JOIN address_order AS AO ON AO.addressId = C.addressId
JOIN order AS O ON O.id = AO.orderId
GROUP BY AO.`orderId`
HAVING (COUNT(AO.`addressId`) > 1);
With these Query I only get a result like this:
+------------+---------+-----------+
| customerId | orderId | addressId |
+------------+---------+-----------+
| 2 | 2 | 2 |
| 4 | 5 | 4 |
+------------+---------+-----------+
I don't see the usage of order table here. However you can use the order table into the consideration if you want to make sure that the order table data and address_order should have data. You can write the query as
select
c.customerId,
ao.orderId,
ao.addressId
from customer c
join address_order ao on ao.addressId = c.addressId
join (
select addressId, count(*) as tot from address_order
group by addressId having tot = 2
)x on x.addressId = ao.addressId
If you want to make sure all the orderId from customer_order are in the order table then you can add another join at the end as
join `order` o on o.id = ao.orderId
Try this
SELECT customerId FROM customer INNER JOIN (SELECT * FROM address_order GROUP BY addressId
HAVING (COUNT(addressId) > 1)) AS t1 ON customer.addressId=t1.addressId
Lets say that I have something table like this:
<b>Name</b>
+---------+--------+
| name_id | name |
+---------+--------+
| 5 | Betti |
| 6 | Derry |
| 7 | Alfred |
| 8 | Elsie |
| 9 | Cinta |
+---------+--------+
<b>Goods</b>
+----------+-----------+
| goods_id | goods |
+----------+-----------+
| 1 | Computer |
| 2 | AC |
| 3 | Microwave |
| 4 | TV |
+----------+-----------+
<b>Transaction</b>
+-------+---------+----------+
| ai_id | name_id | goods_id |
+-------+---------+----------+
| 1 | 7 | 2 |
| 2 | 5 | 4 |
| 3 | 9 | 3 |
+-------+---------+----------+
I want to replace name_id column on Transaction table with name column on Name table with corresponding name_id column and so for goods_id to produce something similar to this table:
<b>Transaction</b>
+-------+--------+-----------+
| ai_id | name | goods |
+-------+--------+-----------+
| 1 | Alfred | AC |
| 2 | Betti | TV |
| 3 | Cinta | Microwave |
+-------+--------+-----------+
If you're looking to just display the information rather than actually "replacing" your tables with new ones, then you could use a SELECT query with a simple INNER JOIN. This way you can display columns from multiple tables.
SELECT T.ai_id, N.Name, G.goods
FROM Transaction T
INNER JOIN Name N ON N.name_id = T.name_id
INNER JOIN Goods G ON G.goods_id = T.goods_id;
Try with inner join
SELECT T.ai_id,N.name,G.goods
FROM Transaction as T
INNER JOIN Goods as G ON T.goods_id = G.goods_id
INNER JOIN Name as N ON N.name_id = T.name_id;
Try this one
select tb3.ai_id,tb2.name,tb1.goods from Goods tb1,Name tb2,Transaction tb3 where tb3.name_id=tb2.name_id and tb3.goods_id=tb1.goods_id order by tb3.ai_id
try this:
SELECT C.ai_id,A.name,B.goods
FROM Transaction C
INNER JOIN Name A
ON A.name_id=C.name_id
INNER JOIN Goods B
ON B.goods_id=C.goods_id;
http://sqlfiddle.com/#!2/3c5f3/8
I have a set of MySQL three tables in a "has many" relationship: deals, orders, and coupons.
Deals
|----|--------------|
| id | title |
|----|--------------|
| 1 | Some deal |
| 2 | Another deal |
|----|--------------|
Orders
|----|---------|-----------|
| id | deal_id | state |
|----|---------|-----------|
| 1 | 1 | purchased |
| 2 | 1 | purchased |
| 3 | 1 | expired |
| 4 | 2 | purchased |
|----|---------|-----------|
Coupons
|----|----------|
| id | order_id |
|----|----------|
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 2 |
| 6 | 4 |
|----|----------|
So, deals have many orders, which have many coupons.
What I'd like to do is select on the deals table while counting the number of purchased orders and coupons.
I know how to get a count on paid orders already:
SELECT deals.*, count(orders.id) AS orders_purchased_count FROM deals
LEFT JOIN orders ON deals.id=orders.deal_id AND orders.state='purchased'
WHERE deal_id < 3
GROUP BY deals.id
Deals
|----|--------------|------------------------|
| id | title | orders_purchased_count |
|----|--------------|------------------------|
| 1 | Some deal | 2 |
| 2 | Another deal | 1 |
|----|--------------|------------------------|
Similarly, I can get a count of coupons for orders:
SELECT orders.*, count(coupons.id) AS coupons_count FROM orders
LEFT JOIN coupons ON orders.id=couoons.orders_id
WHERE orders.state='purchased'
GROUP BY orders.id
Orders
|----|-----------|---------------|
| id | state | coupons_count |
|----|-----------|---------------|
| 1 | purchased | 3 |
| 2 | purchased | 2 |
| 4 | purchased | 1 |
|----|-----------|---------------|
My question is: How do I combine these so that I can add coupons_count next to orders_purchased_count?
Deals
|----|--------------|------------------------|---------------|
| id | title | orders_purchased_count | coupons_count |
|----|--------------|------------------------|---------------|
| 1 | Some deal | 2 | 5 |
| 2 | Another deal | 1 | 1 |
|----|--------------|------------------------|---------------|
The tricky thing, in my case, will be to run the WHERE deal_id < 3 filter when selecting from deals before I join on orders and to run the WHERE orders.state='purchased' filter when selecting from orders before I join on coupons. It's a large dataset and I don't want to load all my orders and coupons into memory for the purpose of joining.
At a loss for how to do this.
Does this work? I couldn't understand your concerns which part was going to be tricky.
SELECT deals.*, COUNT(DISTINCT(orders.id)) AS orders_purchased_count, COUNT(coupons.id) AS coupons_count
FROM deals
LEFT JOIN orders
ON deals.id=orders.deal_id
AND orders.state='purchased'
LEFT JOIN coupons
ON orders.id=coupons.orders_id
WHERE deal_id < 3
GROUP BY deals.id;
Try this one with a co related subquery and join
SELECT deals.*, count(orders.id) AS orders_purchased_count
(
SELECT count(id) FROM coupons WHERE orders_id = orders.id
) AS coupons_count
FROM deals
LEFT JOIN orders ON deals.id=orders.deal_id AND orders.state='purchased'
WHERE deal_id < 3
GROUP BY deals.id