How count result from 3 tables - mysql

Please, take a look in these 3 tables:
Pets
+----+---------+-------+
| id | petname | owner |
+====+=========+=======+
| 1 | chew | 1 |
+----+---------+-------+
| 2 | yo | 2 |
+----+---------+-------+
| 3 | mah | 3 |
+----+---------+-------+
Owners
+----+-------+-----------+
| id | store | ownername |
+====+=======+===========+
| 1 | 1 | Jonh |
+----+-------+-----------+
| 2 | 2 | Joe |
+----+-------+-----------+
| 3 | 3 | Smith |
+----+-------+-----------+
Stores
+----+------------+
| id | storename |
+====+============+
| 1 | Lite Store |
+----+------------+
| 2 | Mega |
+----+------------+
| 3 | Corner |
+----+------------+
Is this possible to get this result?
+------------+------------+
| storename | Total Pets |
+============+============+
| Lite Store | 5 |
+------------+------------+
| Mega | 8 |
+------------+------------+
| Corner | 0 |
+------------+------------+
I tried for hours a lot of subqueries and joins, but I'm missing something, maybe Union?
With below I got close, but still far
SELECT storename, COUNT(distinct stores.storename) as store, count(DISTINCT pets.owner) as petowner from stores inner join owners on owners.id = stores.id inner JOIN pets on pets.owner = stores.id group by stores.id
SELECT stores.storename, COUNT(distinct stores.storename) as store, count(DISTINCT pets.owner) as petowner from stores inner join owners on owners.id = stores.id inner JOIN pets on pets.owner = stores.id group by stores.id
SELECT stores.storename, COUNT(distinct owners.id) as store, count(DISTINCT pets.owner) as petowner from stores inner join owners on owners.id = stores.id inner JOIN pets on pets.owner = stores.id group by stores.id
SELECT COUNT(*),(SELECT COUNT(*) from stores) FROM pets
SELECT COUNT(*),(SELECT DISTINCT(COUNT(*)) from stores),(SELECT DISTINCT(COUNT(*)) FROM owners) FROM pets
SELECT DISTINCT(COUNT(*)), ( select count(DISTINCT(stores.storename)) from stores join owners on stores.id = stores.storename ) FROM pets
select stores.storename, (select count(*) from pets) from stores join owners on stores.id = stores.storename group by storename
select DISTINCT(stores.storename), (select count(*) from pets) from stores join owners on stores.id = stores.storename group by storename
select (count(stores.storename)), (select count(*) from pets) as total from stores join owners on stores.id = stores.storename group by storename
Is there any way to get the result above?
Any help will be great appreciated!

Thank you for providing your queries. I have formed a below query. Request you to try it and see if it works. if not, let me know
Select s.storename, count(p.petname) from pets p join owners o on p.owner=o.id join stores s on o.store=s.id group by 1

Related

Find oldest account per company in sql

I have a few tables that look like the below
Users
-----------------------------------------
| id | policyId | createdAt | updatedAt |
-----------------------------------------
| 1 | 1 | 2017/8/5 | 2017/8/5 |
| 2 | 1 | 2016/4/5 | 2017/8/5 |
| 3 | 2 | 2017/7/2 | 2017/8/5 |
| 4 | 2 | 2018/8/5 | 2017/8/5 |
-----------------------------------------
Policies
------------------------------------------
| id | companyId | createdAt | updatedAt |
------------------------------------------
| 1 | 1 | 2017/8/5 | 2017/8/5 |
| 2 | 2 | 2016/4/5 | 2017/8/5 |
------------------------------------------
Companies
-----------------------------------------
| id | policyId | createdAt | updatedAt |
-----------------------------------------
| 1 | 2 | 2017/8/5 | 2017/8/5 |
| 2 | 1 | 2016/4/5 | 2017/8/5 |
-----------------------------------------
I need to answer the question "What is the id of the user for each company with the oldest account. So the output should look something like this.
Output
----------------------------------
| CompanyId | UserId | CreatedAt |
----------------------------------
| 1 | 2 | 2016/4/5 |
| 2 | 3 | 2017/7/2 |
----------------------------------
What I have gotten so far looks something like this but I know it is no were near correct.
SELECT c.id, MIN(u.createdAt) FROM companies as c
JOIN policies as p on p.companyId = c.id
JOIN users as u on u.policyId = p.id
GROUP BY c.id;
This seems to let me get the oldest date for each company user but I am not sure how to correlate the users back to that date to get the user id's. I am thinking the query above might have to be a sub-query but that is about as far as my sql knowledge goes.
Any help would be appreciated.
I need to join the whole query to itself and join by comapny id and createdAt column.
see demo here: http://sqlfiddle.com/#!9/6f4ea7/22
SELECT c.id as companyID,
u.id as userID,
u.createdAt
FROM companies as c
JOIN policies as p on p.companyId = c.id
JOIN users as u on u.policyId = p.id
JOIN (SELECT c.id as companyID,
min(u.createdAt) as min_dt
FROM companies as c
JOIN policies as p on p.companyId = c.id
JOIN users as u on u.policyId = p.id
GROUP BY c.id) sub
on c.id=sub.companyID
where u.createdAt=sub.min_dt
SELECT p.company_id, u.user_id, MIN(u.createdAt) FROM policies p, user_u,
(SELECT min(createdAt) as minDate, policy_id as policyId from users
GROUP BY policy_id) as sub
WHERE p.id = u.policy_id
AND sub.minDate = u.createdAt
AND sub.policy_id = u.policyId;
It will give u the expected output But some hard coded way
SELECT c.id as companyid,u.id as userid, MIN(u.createdAt) as createdAt FROM company as c
JOIN policies as p on p.cmpid = c.id
JOIN users as u on u.policyId = p.id
GROUP BY c.id,u.id order by MIN(u.createdAt) asc limit 2;

Get default value from JOIN query if join field value doesn't exist in another table

I have two tables customers and reviews. The structure is like this:
customers:-
|---------------------------------|
| id | name |
|---------------------------------|
| 1 | Thutmekri |
|---------------------------------|
| 3 | Conan |
|---------------------------------|
reviews:-
|-------------------------------------------|
| id | business_id | customer_id |
|-------------------------------------------|
| 1 | 1 | 1 |
|-------------------------------------------|
| 2 | 1 | 2 |
|-------------------------------------------|
| 3 | 1 | 3 |
|-------------------------------------------|
customer_id of reviews is id of customer.
The join query,
SELECT customers.name, reviews.id as review_id
FROM customers, reviews
WHERE customers.id = reviews.customer_id
returns the dataset like this:-
|----------------------------------|
| review_id | name |
|----------------------------------|
| 1 | Thutmekri |
|----------------------------------|
| 3 | Conan |
|----------------------------------|
But I want it to return:-
|----------------------------------|
| review_id | name |
|----------------------------------|
| 1 | Thutmekri |
|----------------------------------|
| 2 | N/A |
|----------------------------------|
| 3 | Conan |
|----------------------------------|
For customer_id in reviews, which doesn't have any data in customers table, I want 'N/A' to be displayed. How can I do it?
The following query also didn't help
SELECT reviews.id as review_id, COALESCE( name, 'N/A' )
FROM customers, reviews
WHERE customers.id = reviews.customer_id
Use a left join and switch the order of the tables in the join:
SELECT
r.id AS review_id,
COALESCE(c.name, 'N/A') AS name
FROM reviews r
LEFT JOIN customers c
ON c.id = r.customer_id;
SQLFiddle
Try this :
SELECT r.id as review_id, COALESCE( c.name, 'N/A' ) FROM reviews r
LEFT JOIN customers c ON c.id = r.customer_id
Use the Right outer join to achieve this:
SELECT
reviews.id as review_id,
COALESCE(name, 'N/A' )
FROM customers
RIGHT JOIN reviews
ON customers.id = reviews.customer_id;
You can use below query
SELECT
R.id AS review_id,
COALESCE(C.name, 'N/A') AS name FROM reviews R LEFT JOIN customers C ON R.customer_id = C.id ;

Get the count of records for table with foreign key

I have the following tables:
Persons:
person_id | name |
-------------------------
1 | John |
2 | Adam |
3 | Elen |
-------------------------
Orders:
order_id | person_id | product |
---------------------------------------------
1 | 1 | TV |
2 | 1 | Radio |
3 | 1 | toothbrush |
4 | 2 | mp3 player |
5 | 2 | watch |
6 | 3 | ps 3 |
---------------------------------------------
Now I need to query above tables to get the following result:
person_id | name | order_count |
-----------------------------------------
1 | John | 3 |
2 | Adam | 2 |
3 | Elen | 1 |
-----------------------------------------
I tried something like:
SELECT u.person_id, u.name, COUNT(o.order_id) FROM persons AS p LEFT JOIN orders AS o ON (p.person_id=o.person_id);
unfortunately this doesn't work. Do you have any idea how to solve this ?
select Persons.person_id, Persons.name, p.order_count
from Persons
inner join (select person_id, count(*) as order_count from Orders group by person_id) p
on Persons.person_id = p.person_id
If you need also get that persons, who doesn't have any orders, then use left join instead of inner join
TRY THIS
SELECT persons.id, persons.name, COUNT(orders.id) AS order_count FROM orders LEFT JOIN persons ON (persons.person_id=orders.person_id) GROUP BY persons.name
Try this....
"select o.person_id,p.name,count(o.person_id) as order_count from tblorders o
Join tblpersons p on o.person_id=p.person_id
group by o.person_id,p.name"
Try this
select o.person_id,p.name,count(o.person_id) as order_count from tblorders o
Join tblpersons p on o.person_id=p.person_id
group by o.person_id,p.name
select p.person_id, p.name, o.cnt
from Persons p
left join
(select person_id , count(order_id) as cnt from Orders group by person_id) o
on p.person_id = o.person_id

MYSQL JOIN two tables limit results from second table by date

I am trying to retrieve date from two tables using a MYSQL query. I want to join them together were categories.cat_id=topics.topic_cat. Multiple entries may have the same topic_cat, so I only want to SELECT the most recent, which is equal to MAX(topic_date).
The following query shows the correct information from topics, with only one result per topic_cat and that result having the most recent date.
SELECT topic_subject, topic_cat, topic_date
FROM topics
GROUP BY topic_cat DESC
Multiple rows may have the same value for topic_cat, but I only want to retrieve and join only the most recent, MAX(topic_date) and then join to a query which shows the following information from the categories table.
SELECT categories.cat_id, categories.cat_name, categories.cat_description, topics.topic_subject, topics.topic_cat, topics.topic_date, topics.topic_by
FROM categories
LEFT JOIN topics
ON categories.cat_id=topics.topic_cat
GROUP BY cat_id;
This query displays the correct information, except one thing. It shows the topic_cat with the oldest entry, or MIN(topic_date). I have tried the following to get the topic_cat by newest entry or MAX(topic_date), but without success.
SELECT categories.cat_id, categories.cat_name, categories.cat_description
FROM categories
LEFT JOIN (SELECT topic_subject, topic_cat, topic_date, topic_by
FROM topics
GROUP BY topic_cat DESC) AS topics
ON categories.cat_id=topics.topic_cat
Any help or suggestions would be greatly appreciated.
Ok, so here is the sample data and associated desired result.
Table 1 = categories
_______________________________________________________
| cat_id | cat_name | cat_description |
-------------------------------------------------------
| 1 | james | Some information about james|
-------------------------------------------------------
| 2 | myo | Some information about myo |
-------------------------------------------------------
| 3 | brandon | Some information about brandon |
-------------------------------------------------------
Table 2 = topics
__________________________________________________
| topic_subject | topic_cat | topic_date | topic_by |
----------------------------------------------------------
| marcos | 2 | 2013-9-28 | User 1 |
---------------------------------------------------------
| ferdinand | 2 | 2013-9-29 | User 2 |
---------------------------------------------------------
| maria luisa | 2 | 2013-9-30 | User 1 |
---------------------------------------------------------
| Isabella | 1 | 2013-8-24 | User 3 |
--------------------------------------------------------
| Carlos | 3 | 2012-6-21 | User 2 |
--------------------------------------------------------
| Enrique | 3 | 2011-4-2 | User 3 |
---------------------------------------------------------
I would like the query to return the following data based on the above tables:
_________________________________________________________________________________________________
| cat_id | cat_name | cat_description | topic_subject | topic_cat | topic_date | topic_by |
----------------------------------------------------------------------------------------------------------------
| 1 | james | Some information about james | Isabella | 1 | 2013-8-24 | User 3 |
----------------------------------------------------------------------------------------------------------------
| 2 | myo | Some information about myo | maria luisa | 2 | 2013-9-30 | User 1 |
----------------------------------------------------------------------------------------------------------------
| 3 | brandon | Some information about brandon | Carlos | 3 | 2012-6-21 | User 2 |
----------------------------------------------------------------------------------------------------------------
I hope that clarifies things.
Try This:
###
SELECT * FROM categories c
LEFT JOIN topics t ON c.cat_id = t.topic_cat
WHERE c.cat_id IN (SELECT t1.cat_id FROM (
SELECT c.cat_id, c.cat_name, MAX(t.topic_date) AS maxdate FROM categories c
LEFT JOIN topics t ON c.cat_id = t.topic_cat
GROUP BY c.cat_name
) as t1 WHERE t1.maxdate = t.topic_date OR t.topic_date IS NULL );
### without nulls
SELECT * FROM categories c
LEFT JOIN topics t ON c.cat_id = t.topic_cat
WHERE c.cat_id IN (SELECT t1.cat_id FROM (
SELECT c.cat_id, c.cat_name, MAX(t.topic_date) AS maxdate FROM categories c
LEFT JOIN topics t ON c.cat_id = t.topic_cat
GROUP BY c.cat_name
) as t1 WHERE t1.maxdate = t.topic_date);
Try changing
LEFT JOIN (SELECT topic_subject, topic_cat, topic_date, topic_by
FROM topics
GROUP BY topic_cat DESC) AS topics
to:
LEFT JOIN (SELECT topic_subject, topic_cat, topic_date, topic_by
FROM topics
GROUP BY topic_cat
ORDER BY topic_date DESC
LIMIT 0,1) AS topics

find multiple records on basis of multiple fields in mysql table

I have mysql table of products. Which have field names like id, name, sku, programme,buyurl etc. Now I want to find duplicate record on the basis of sku but with the different programme name. I am actually doing it for price compare feature.
Here is my code for finding duplicate records, which is fine but my problem is it have same programme names, and I need it for different.
SELECT id, name, products.sku FROM products
INNER JOIN (SELECT sku FROM products
GROUP BY sku HAVING count(sku) > 1) dup ON products.sku= dup.sku
Sample data:
id | name | sku | programme | buyurl
1 | pro1 | 123 | KFC | kfc.com
2 | pro2 | 123 | McDonald | mcdonald.com
3 | pro3 | 456 | McDonal | mcdonald.com
4 | pro4 | 123 | KFC | kfc.com
Required output should be
id | name | sku | programme | buyurl
1 | pro1 | 123 | KFC | kfc.com
2 | pro2 | 123 | McDonald | mcdonald.com
As there sku are same and programme are different.
Any help will be appreciated.
If I understood you correctly, this query would work for you:
SELECT p1.id, p1.name, p1.sku, p1.programme
FROM product p1 JOIN product p2
ON p1.sku = p2.sku AND p1. programme <> p2.programme
If not then please add some sample data and expected result.
Based on sample data, try this query:
SELECT * FROM product
WHERE id IN(
SELECT p1.id
FROM (SELECT MIN(id) as id, sku, programme FROM product GROUP BY sku, programme) p1
JOIN (SELECT MIN(id) as id, sku, programme FROM product GROUP BY sku, programme) p2
ON p1.sku = p2.sku AND p1.programme <> p2.programme
)
You can try
SELECT p.id, name, sku, programme, buyurl
FROM
(
SELECT MIN(t1.id) id
FROM products t1 JOIN products t2
ON t1.sku = t2.sku
AND t1.programme <> t2.programme
GROUP BY t1.sku, t1.programme
) q JOIN products p
ON q.id = p.id
Output:
| ID | NAME | SKU | PROGRAMME | BUYURL |
|----|------|-----|-----------|--------------|
| 1 | pro1 | 123 | KFC | kfc.com |
| 2 | pro2 | 123 | McDonald | mcdonald.com |
Here is SQLFiddle demo