Correlated subquery display count column - mysql

I have the following query which works fine:
SELECT c.cust_id, c.cust_type_cd, c.city, count(*) as `count`
FROM customer c
INNER JOIN account a
ON a.cust_id = c.cust_id
GROUP BY c.cust_id
HAVING `count` = 2;
Result:
+---------+--------------+---------+-------+
| cust_id | cust_type_cd | city | count |
+---------+--------------+---------+-------+
| 2 | I | Woburn | 2 |
| 3 | I | Quincy | 2 |
| 6 | I | Waltham | 2 |
| 8 | I | Salem | 2 |
| 10 | B | Salem | 2 |
+---------+--------------+---------+-------+
I would like to achieve the same result using a correlated subquery. I have not been able to make a "count" column as show above:
SELECT c.cust_id, c.cust_type_cd, c.city
FROM customer c
WHERE 2 = (
SELECT COUNT(*)
FROM account a
WHERE a.cust_id = c.cust_id
);
Result:
+---------+--------------+---------+
| cust_id | cust_type_cd | city |
+---------+--------------+---------+
| 2 | I | Woburn |
| 3 | I | Quincy |
| 6 | I | Waltham |
| 8 | I | Salem |
| 10 | B | Salem |
+---------+--------------+---------+
How can I achieve the same result as the one using the INNER JOIN and have a "count" column?

Not sure why you wanted this but you also need to specify the subquery in the SELECT part,
SELECT c.cust_id, c.cust_type_cd, c.city, (SELECT COUNT(*)
FROM account a
WHERE a.cust_id = c.cust_id) AS `count`
FROM customer c
WHERE 2 = (
SELECT COUNT(*)
FROM account a
WHERE a.cust_id = c.cust_id
);

Related

How to COUNT and SELECT with WHERE in sql?

I have two tables user and group and also a usergroup as a link table which contains which users exist in a group.
user table
+-----+-------+
| id | name |
+-----+-------+
| U12 | John |
| U13 | Rick |
| U14 | Morty |
| U15 | Alex |
| U16 | Felix |
+-----+-------+
group table
+-----+--------+--------+
| id | name | points |
+-----+--------+--------+
| G12 | Red | 11 |
| G13 | Blue | 22 |
| G14 | Green | 55 |
| G15 | Yellow | 64 |
| G16 | Orange | 23 |
+-----+--------+--------+
usergroup table
+----+---------+----------+
| id | user_id | group_id |
+----+---------+----------+
| 1 | U12 | G12 |
| 2 | U14 | G12 |
| 3 | U15 | G12 |
| 4 | U15 | G15 |
| 5 | U12 | G13 |
+----+---------+----------+
To select the groups that a particular user is in, I can just do
SELECT group.*
FROM usergroup
INNER JOIN group
ON group.id = usergroup.group_id
WHERE usergroup.user_id = ?
But how to also simultaneously select the number of total users in the same group?
Expected Sample Output - for the groups that user U12 is in, along with total user count
+-----+------+--------+-------------+
| id | name | points | users_count |
+-----+------+--------+-------------+
| G12 | Red | 11 | 3 |
| G13 | Blue | 22 | 1 |
+-----+------+--------+-------------+
use scalar subquery
SELECT `group`.* , (select count(id) from usergroup a where a.group_id=usergroup.group_id ) as user_count
FROM usergroup
INNER JOIN `group` ON `group`.id = usergroup.group_id
WHERE usergroup.user_id = 'U12'
SELECT y.id, y.name, y.points, y.users_count
FROM usergroup x INNER JOIN
( SELECT b.id, b.name, b.points, count(a.user_id) as users_count
FROM usergroup a INNER JOIN group b
ON a.group_id = b.id
GROUP BY b.id ) AS y
ON x.group_id = y.id
WHERE x.user_id = 'U12'
SELECT a.group_id,
a.NAME,
a.points,
c.user_count
FROM group a,
usergroup b,
(SELECT x.group_id,
Count(*) AS user_count
FROM usergroup x
GROUP BY x.group_id) c
WHERE a.group_id = b.group_id
AND a.group_id = c.group_id
AND user_id = 'U12';
SELECT group.*, count(usergroup.group_id),usergroup.user_id
FROM usergroup
INNER JOIN group
ON group.id = usergroup.id
GROUP BY usergroup.group_id
Having usergroup.user_id = 'U12'
You need to use group by with having.
Check it on SQLFiddle: sqlfiddle.com/#!9/b63e13/3/0

mysql - joins with sub queries with sub query where conditions using main query fields

i have a complaint table
|------------------------|
| cid | desc |
|------------------------|
| 1 | faulty |
| 2 | broken |
| 3 | spoiled |
|------------------------|
and an assignment table
|------------------------------------|
| aid | cid | empid |
|------------------------------------|
| 1 | 1 | 1 |
| 2 | 1 | 5 |
| 3 | 2 | 2 |
| 4 | 2 | |
| 5 | 3 | 2 |
| 6 | 3 | 7 |
|------------------------------------|
each complaint can be assigned to atmost two employees
i need to display a list in the below format
|---------------------------------------------------|
| cid | desc | emp1id | emp2id |
|------------------------|--------------------------|
| 1 | faulty | 1 | 5 |
| 2 | broken | 2 | |
| 3 | spoiled | 2 | 7 |
|------------------------|--------------------------|
i wrote the query like this
select c.cid, c.desc, a1.empid as emp1id, a2.empid as emp2id
from complaint c
left join (
select aid, cid, empid
from assignment aa
where aa.cid = c.cid
limit 0,1
) as a1 on a1.cid = c.cid
left join (
select aid, cid, empid
from assignment ab
where ab.cid = c.cid
limit 1,1
) as a2 on a2.cid = c.cid
but it is not working, i am getting error for c.cid in sub queries. how to do?
This might work? (I don't have mySql installed)
select c.cid,
c.desc,
(
select aid, cid, empid
from assignment aa
where aa.cid = c.cid
limit 0,1
) as emp1id,
(
select aid, cid, empid
from assignment ab
where ab.cid = c.cid
limit 1,1
) as emp2id
from complaint c

How to get name and manager name

How to get name and manager name
+----+-----------+---------+
| id | name | manager |
+----+-----------+---------+
| 1 | bhupendra | 0 |
| 2 | shyam | 1 |
| 3 | ram | 1 |
| 4 | geeta | 2 |
| 5 | sita | 1 |
+----+-----------+---------+
i need result like
+-----------+-----------+
| name | manager |
+-----------+-----------+
| bhupendra | |
| shyam | bhupendra |
| ram | bhupendra |
| geeta | shyam |
| sita | bhupendra |
+-----------+-----------+
You could self-join the id column on the manager column:
SELECT e.name AS name, m.name AS manager
FROM employee e
LEFT JOIN employee m ON m.id = e.manager
You should use the same table twice using alias
select a.name, b.name as manager
from my_table a
left join my_table b on a.manager = b.id
Check this out
with recursive cte (id, name, parent_id) as (
select id,
name,
manager
from employee
union all
select p.id,
p.name,
p.manager
from employee e
inner join cte
on p.manager = cte.id
)
select * from cte;

sql Select Orders with multiple addresses

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

search query joining 3 tables, 1 table has date

i have 3 tables, the employee table, educational background and job_title,
i need to join the 3 tables and select the latest year the employee is graduated. the result query i need is listed below.
EMPLOYEE TABLE
|ID | employee_id | Name |
| 1 | 123 | Jewel Brin |
| 2 | 554 | Donna Ferry |
| 3 | 853 | Ricky David |
educational background
|ID | employee_id | School/level | date graduated |
| 1 | 123 | highschool | 2007 |
| 2 | 123 | college | 2011 |
| 3 | 554 | college | 2010 |
| 4 | 554 | masteral | 2013 |
job title
|ID | employee_id | Job description |
| 1 | 123 | Free lancer |
| 2 | 554 | admin assistant |
| 3 | 853 | Support Admin |
i need to select the latest date info of the employee's educational background
the result would be:
result query
|ID | employee_id | Name | Job title | year_graduated | school_institute |
| 1 | 123 | Jewel Brin | Free Lancer | 2011 | college |
| 2 | 554 | Donna Ferry | Admin Assistant | 2013 | masteral |
| 3 | 853 | Ricky David | Support Admin | Null | Null
Forgot to mention, this is MySQL :)
SELECT e.employee_id, Name, `Job description` AS `Job title`, year_graduated, school_institute
FROM `employee` e
INNER JOIN job_title j ON j.employee_id = e.employee_id
LEFT JOIN (SELECT ID, `School/level` AS school_institute, employee_id, `date graduated` AS year_graduated FROM `educational background` b
INNER JOIN (
SELECT ID, MAX(`date graduated`) AS max_date FROM `educational background` GROUP BY employee_id
) b2
ON b2.max_date = b.year_graduated AND b2.ID = b.ID
) bb ON bb.employee_id = e.employee_id
In SQL Server :-
Select *
from
(
Select e.ID,e.employee_ID,e.Name,
b.Level,j.[Job description],
rn = row_number()
over (partition by e.Employee_ID order by [date graduated] desc)
From Employee e
left join Background b
on e.Employee_ID = b.Employee_ID
left join Jobtitle j
on j.Employee_ID = b.Employee_ID
)a
where a.rn=1
SQL FIDDLE
For Mysql you can try this
SELECT DISTINCT
e.employee_id,
e.Name,
j.Job_description,
eb.year_graduated,
eb.level
FROM
EMPLOYEE e
LEFT JOIN
(SELECT
*,
MAX(t.date_graduated) year_graduated
FROM
(SELECT * FROM Background ORDER BY date_graduated DESC) t
GROUP BY employee_id) eb
ON (e.employee_id = eb.employee_id)
LEFT JOIN JobTitle j
ON (e.employee_id = j.employee_id)
See Fiddle Demo