i've 4 tables. region, land, house, and goods.
land have one-to-one rels. with region.
land have one-to-many rels. with house.
house have one-to-many rels. with goods.
sqlfiddle: http://sqlfiddle.com/#!9/5eaec
current query:
SELECT
Sum(land.wide) AS land_wide,
Sum(house.price) AS house_price,
Sum(goods.amount) AS goods_amount,
Sum(goods.price) AS goods_price,
region.region_name
FROM
land
LEFT JOIN house ON house.land_id = land.id
LEFT JOIN goods ON goods.house_id = house.id
LEFT JOIN region ON land.region_id = region.id
GROUP BY
region.region_name
ORDER BY
region.id ASC
but not works as expected.
desired output:
+-----------+-------------+-------------+--------------+---------+
| land_wide | house_price | goods_price | goods_amount | region |
+-----------+-------------+-------------+--------------+---------+
| 510 | 57910 | 1900 | 56 | Tokyo |
| | | | | Osaka |
| | | | | Nagoya |
| | | | | Sapporo |
+-----------+-------------+-------------+--------------+---------+
Would someone kindly offer me a solution which would help? I am pretty sure it could be done in SQL?
SELECT
land_wides.land_wide,
house_prices.house_price,
goods_amounts_prices.goods_price,
goods_amounts_prices.goods_amount,
region.region_name
FROM region
LEFT JOIN (SELECT
Sum(land.wide) AS land_wide,
region.id AS region_id
FROM region
LEFT JOIN land ON land.region_id = region.id
GROUP BY region.id) land_wides ON region.id = land_wides.region_id
LEFT JOIN (SELECT
Sum(house.price) AS house_price,
region.id AS region_id
FROM region
LEFT JOIN land ON land.region_id = region.id
LEFT JOIN house ON house.land_id = land.id
GROUP BY region.id) house_prices ON region.id = house_prices.region_id
LEFT JOIN (SELECT
Sum(goods.amount) AS goods_amount,
Sum(goods.price) AS goods_price,
region.id AS region_id
FROM region
LEFT JOIN land ON land.region_id = region.id
LEFT JOIN house ON house.land_id = land.id
LEFT JOIN goods ON goods.house_id = house.id
GROUP BY region.id) goods_amounts_prices on goods_amounts_prices.region_id = region.id
ORDER BY region.id
Left join should be inner join. You want to have grouping on matching rows. Not unmatched rows, hence grouping on sum.
Related
I've a food listing system. It has five tables.
REGIONS
BANNERS
CUISINE
RESTAURANTS
RESTAURANT_SPONSORED
BANNERS, CUISINE and RESTAURANT_SPONSORED table records the revenue of advertising.
I want to generate this table.
name | banner_revenue | cuisine_revenue | restaurant_promotions
------------------------------------------------------------------
NY | 10,000 | 4,800 | 12,000
Paris | NULL | 8,000 | 8,000
London | NULL | NULL | 2,000
This query will output,
SELECT r.name,
sb.fee,
sc.fee
FROM REGIONS r
LEFT JOIN (SELECT sum(b.fee) fee,
b.region_id
FROM BANNERS b
GROUP BY b.region_id) sb
ON sb.region_id = r.id
LEFT JOIN (SELECT sum(c.fee) fee,
c.region_id
FROM CUISINE c
GROUP BY c.region_id) sc
ON sc.region_id = r.id;
name | banner_revenue | cuisine_revenue |
--------------------------------------------
NY | 10,000 | 4,800 |
Paris | NULL | 8,000 |
London | NULL | NULL |
But how do I get restaurant_promotions part? Which is needed a nested left join.
DB Fiddle demo
modify your query to :
SELECT r.name,
sb.fee,
sc.fee,
sr.fee
FROM REGIONS r
LEFT JOIN (SELECT sum(b.fee) fee,
b.region_id
FROM BANNERS b
GROUP BY b.region_id) sb
ON sb.region_id = r.id
LEFT JOIN (SELECT sum(c.fee) fee,
c.region_id
FROM CUISINE c
GROUP BY c.region_id) sc
ON sc.region_id = r.id
LEFT JOIN(SELECT sum(RESTAURANT_SPONSORED.fee) fee,
R.region_id
FROM RESTAURANTS R
LEFT JOIN RESTAURANT_SPONSORED ON(RESTAURANT_SPONSORED.restaurant_id = R.id)
GROUP BY R.region_id) sr
ON sr.region_id= r.id
this should work
I have three tables like this:
Animal
| id | cat_id | horse_id | dog_id |
|:--:|:------:|:--------:|--------|
| 1 | 15 | 16 | 17 |
Cat
| id | lang_id |
|:--:|:-------:|
| 15 | 3716 |
Horse
| id | lang_id |
|:--:|:-------:|
| 16 | 3717 |
Dog
| id | lang_id |
|:--:|:-------:|
| 17 | 3718 |
Language
| id | en |
|:----:|:--------------:|
| 3716 | BRAVE LEGEND |
| 3717 | N Rawiller |
| 3718 | DRAGON GENERAL |
I want to get all the animals en name from Language table through each animal's table lang_id. It would be like by using Animal: cat_id -> Cat: lang_id -> Language: en. The final results would be like:
| animal_id | cat_name | horse_name | dog_name |
|:---------:|:------------:|:----------:|:--------------:|
| 1 | BRAVE LEGEND | N Rawiller | DRAGON GENERAL |
I am trying to use this:
select animal.id, lang.* from animal
left join cat on animal.cat_id = cat.id
left join horse on animal.horse_id = horse.id
left join dog on animal.dog_id = dog.id
left join lang on cat.lang_id = lang.id or (horse.lang_id = lang.id) or (dog.lang_id = lang.id)
where animal.id = 1
But I can't get cat_name, dog_name, horse_name because it's all coming from the same Language table.
Try below query:
You need to JOIN lang table multiple times, using one JOIN with multiple OR will not give you desired result,
SELECT animal.id, lang.en as cat_name,l1.en as horse_name,l2.en as dog_name
FROM animal
LEFT JOIN cat ON animal.cat_id = cat.id
LEFT JOIN horse ON animal.horse_id = horse.id
LEFT JOIN dog ON animal.dog_id = dog.id
LEFT JOIN lang ON cat.lang_id = lang.id
LEFT JOIN lang l1 ON horse.lang_id = l1.id
LEFT JOIN lang l2 ON dog.lang_id = l2.id
WHERE animal.id = 1
Try this:
select animal.id, lang1.cat_name, lang2.horse_name, lang3.dog_name
from animal
left join cat on animal.cat_id = cat.id
left join horse on animal.horse_id = horse.id
left join dog on animal.dog_id = dog.id
left join lang AS lang1 on cat.lang_id = lang1.id
left join lang AS lang2 ON horse.lang_id = lang2.id
left join lang AS lang3 ON (dog.lang_id = lang3.id)
where animal.id = 1
Try this:
SELECT a.id, lang1.en as cat_name,lang2.en as horse_name,lang3.en as dog_name
FROM `animal` a
LEFT JOIN cat c ON c.id = a.cat_id
LEFT JOIN LANGUAGE l on l.id=c.lang_id
LEFT JOIN dog d ON d.id = a.dog_id
LEFT JOIN horse h ON h.id = a.horse_id
LEFT JOIN language lang1 ON c.lang_id=lang1.id
LEFT JOIN language lang2 ON h.lang_id=lang2.id
LEFT JOIN language lang3 ON d.lang_id=lang3.id
This is my sql table structure:
Table1: details
|--id--|--id_user--|--price--|
| 1 | 1 | 10 |
| 2 | 2 | 15 |
| 3 | 1 | 25 |
| 4 | 3 | 30 |
| 5 | 3 | 7 |
------------------------------
Table2: users
|--id--|--id_country--|
| 1 | 1 |
| 2 | 2 |
| 3 | 0 |
-----------------------
Table3: country
|--id--|--country--|
| 1 | France |
| 2 | Italy |
--------------------
What I need is to get the SUM of price by country:
SELECT c.country, SUM(d.price) AS price
FROM details d
INNER JOIN users u ON u.id = d.id_user
INNER JOIN country c ON c.id = u.id_country
GROUP BY c.country
ORDER BY c.country
I get this:
|--country--|--price--|
| France | 35 |
| Italy | 15 |
-----------------------
BUT I'd need to get this:
|--country--|--price--|
| France | 35 |
| Italy | 15 |
| Undefined | 37 |
-----------------------
where undefined would be if id_country=0. (I can't add to country table the id=0 or id=undefined, it will messed up other things). Right now I'm achieving this by two separate queries, the second one is:
SELECT SUM(d.price) as price
FROM details d
INNER JOIN users u ON u.id = d.id_user AND u.id_country=0
GROUP BY u.id_country
I'm thinking if... is it possible to do this in one query?
You need to use left join in this case:
SELECT c.country, SUM(d.price) AS price
FROM details d
LEFT JOIN users u ON u.id = d.id_user
LEFT JOIN country c ON c.id = u.id_country
GROUP BY c.country
ORDER BY c.country
If you use INNER JOIN, you will only get results that exists in both tables.
To replace NULL with Undefined use:
SELECT IFNULL(c.country,'Undefined') AS Country, SUM(d.price) AS price
FROM details d
LEFT JOIN users u ON u.id = d.id_user
LEFT JOIN country c ON c.id = u.id_country
GROUP BY c.country
ORDER BY c.country
One way to sort to get Undefined last is to add a Sortfield
SELECT A.Country,A.Price FROM (
SELECT IFNULL(c.country,'Undefined') AS Country, SUM(d.price) AS price, IFNULL(c.Country,'ZZZZZZZZ') AS Sort
FROM details d
LEFT JOIN users u ON u.id = d.id_user
LEFT JOIN country c ON c.id = u.id_country
GROUP BY c.country
) A
ORDER BY A.Sort
Edit: ORDER BY suggested in comments
SELECT IFNULL(c.country,'Undefined') AS Country, SUM(d.price) AS price
FROM details d
LEFT JOIN users u ON u.id = d.id_user
LEFT JOIN country c ON c.id = u.id_country
GROUP BY c.country
ORDER BY c.country IS NULL, c.country
Try below query.
SELECT
CASE
WHEN c.country is NULL THEN 'Undefined'
ELSE c.country
END as country
, SUM(d.price) AS price
FROM users u
left JOIN details d ON u.id = d.id_user
left JOIN country c ON c.id = u.id_country
GROUP BY c.country
ORDER BY c.country
For Demo :
SqlfiddlE Demo :
Please let us know if you have any que.
I have 3 tables
Table cases: docket is pk
| docket | dt_file |
-----------------------
|AA-0322 | 01-22-2015 |
|AA-0431 | 03-21-2014 |
Table parties:
| id | docket | name |
----------------------------
| 1 | AA-0322 | Bob |
| 2 | AA-0322 | John |
Table motions:
| id | docket | motion |
-----------------------------
| 1 | AA-0322 | Summons|
| 2 | AA-0322 | Guilty |
I want to count the number of fields in parties and motion that have the same docket and then make a table with table.cases with the dt_file
example:
| docket | party_count | motion_count| dt_file |
-----------------------------------------------
AA-0322| 2 | 2 | 02-22-2015|
I also want to filter by dt_file, so adding a WHERE statement ex:
WHERE YEAR(dt_file) = '2015'
So far i've came up with this, but I havn't had success joining table.cases with dt_file correctly.
SELECT p.docket, p.party_count, m.motion_count
FROM
(SELECT docket, COUNT(docket) AS party_count
FROM parties
GROUP BY docket) AS p
INNER JOIN
(SELECT docket, COUNT(docket) AS motion_count
FROM motions
GROUP BY docket) AS m
ON p.docket = m.docket
Your query seems correct. You just need to add cases to the from clause:
SELECT c.docket, p.party_count, m.motion_count, c.dt_file
FROM cases c JOIN
(SELECT docket, COUNT(docket) AS party_count
FROM parties
GROUP BY docket
) p
ON c.docket = p.docket INNER JOIN
(SELECT docket, COUNT(docket) AS motion_count
FROM motions
GROUP BY docket
) m
ON c.docket = m.docket;
If you want all dockets, even those where there are no motions or parties, then use LEFT JOIN.
Let this be another example.
Select
p.docket,
COUNT(p.docket) As party_count,
COUNT(m.docket) As motion_count,
p.dt_file
From
cases As c
Inner Join parties As p
On c.docket = p.docket
Inner Join motions As m
On c.docket = m.docket
Group By
p.docket,
p.dt_file
Try this:
SELECT p.docket, p.party_count, m.motion_count, c.dt_file
FROM
(SELECT docket, COUNT(docket) AS party_count
FROM parties
GROUP BY docket) AS p
INNER JOIN
(SELECT docket, COUNT(docket) AS motion_count
FROM motions
GROUP BY docket) AS m
ON p.docket = m.docket
INNER JOIN cases c
ON p.docket = c.docket
WHERE YEAR(c.dt_file) = '2015'
I have a mysql select query like this:
select r.restaurant_id, r.restaurant_name, r.city_id, c.name
from restaurants r
inner join cities c on c.id = r.city_id;
This is the result of above query:
+---------------+----------------------+---------+-------------+
| restaurant_id | restaurant_name | city_id | name |
+---------------+----------------------+---------+-------------+
| 7 | Somasiri Bake House | 5 | Mumbai |
| 8 | Indian Bake House | 7 | Chennai |
| 9 | KFC Rest | 5 | Mumbai |
| 10 | Indian t | 5 | Mumbai |
+---------------+----------------------+---------+-------------+
Now I want to display all the available cities with the number of restaurants existing to one city.
Eg: Mumbai (3), Chennai(1) and so on
I tried it like below with mysql COUN(), but it doesn't work for me.
SELECT c.name, count(r.city_id) AS count
FROM cities c
INNER JOIN restaurants r ON c.id = r.city_id;
Can anybody tell me what is the wrong with this?
Hope somebody may help me out.
Thank you.
SELECT c.name, COALESCE(count(r.city_id), 0) AS count
FROM cities c
LEFT JOIN restaurants r ON c.id = r.city_id
GROUP BY c.id
Use a simple group by if you don't want restaurant data:
select c.name, count(r.city_id) as available
from cities c
left join restaurants r on c.id = r.city_id
group by r.city_id
See SQLFiddle.
Or, if you want restaurant data too, select from cities first, then left join to other tables so cities without restaurants still get returned. Add a left join to a subquery that calculates each city's frequency:
select
r.restaurant_id,
r.restaurant_name,
c.id,
c.name,
coalesce(available, 0) available
from cities c
left join restaurants r on c.id = r.city_id
left join (select city_id, count(*) available from restaurants group by 1) a
on a.city_id = r.city_id
See SQLFiddle.
That's called a grouping or aggregate query, you need to tell it how to group your elements.
Just add
GROUP BY r.restaurant_id, r.restaurant_name, r.city_id, c.name
at the end, before your final semi-colon.