'How to write SQL sub-query in SQL?
Here is sample data I am looking for total buying trade value and total selling trades value based on country.
Here are two tables, country, and trades Table [companies]:
+-------------+--------------------+
| name| country |
+-------------+--------------------+
| Alice s.p. | Wonderland |
| Y-zap | Wonderland |
| Absolute | Mathlands |
| Arcus t.g. | Mathlands |
| Lil Mermaid | Underwater Kingdom |
| None at all | Nothingland |
+-------------+--------------------+
Table [trades]:
trades:
+----------+-------------+------------+-------+
| id | seller | buyer | value |
+----------+-------------+------------+-------+
| 20121107 | Lil Mermaid | Alice s.p. | 10 |
| 20123112 | Arcus t.g. | Y-zap | 30 |
| 20120125 | Alice s.p. | Arcus t.g. | 100 |
| 20120216 | Lil Mermaid | Absolute | 30 |
| 20120217 | Lil Mermaid | Absolute | 50 |
+----------+-------------+------------+-------+
Expected Output:
+--------------------+--------+--------+
| country| buyer | seller|
+--------------------+--------+--------+
| Mathlands | 180 | 30 |
| Nothingland | 0 | 0 |
| Underwater Kingdom | 0 | 90 |
| Wonderland | 40 | 100 |
+--------------------+--------+--------+
I am trying this: It gives only one value column and it doesn't show the 0 trade country that I want to show also.
select country, sum(value), sum(value)
from
(select a.buyer as export, a.seller as import, value, b.country as country
from trades as a
join companies as b
on a.seller=b.name)
group by country
order by country
Solution 1:[1]
Join country
to distinct rows of trades
which contain only buyer or seller and aggregate conditionally:
SELECT c.country,
SUM(CASE WHEN buyer IS NOT NULL THEN value ELSE 0 END) buyer,
SUM(CASE WHEN seller IS NOT NULL THEN value ELSE 0 END) seller
FROM country c
LEFT JOIN (
SELECT buyer, null seller, value FROM trades
UNION ALL
SELECT null, seller, value FROM trades
) t ON c.name IN (t.buyer, t.seller)
GROUP BY c.country
Or, with SUM() window function:
SELECT DISTINCT c.country,
SUM(CASE WHEN c.name = t.buyer THEN value ELSE 0 END) OVER (PARTITION BY c.country) buyer,
SUM(CASE WHEN c.name = t.seller THEN value ELSE 0 END) OVER (PARTITION BY c.country) seller
FROM country c LEFT JOIN trades t
ON c.name IN (t.buyer, t.seller)
See the demo.
Solution 2:[2]
Try CTE:
WITH sold AS (
SELECT sum(t.value) AS value, c.country FROM trades AS t INNER JOIN companies AS c ON (t.seller = c.name) GROUP BY c.country
), buyed AS (
SELECT sum(t.value) AS value, c.country FROM trades AS t INNER JOIN companies AS c ON (t.buyer = c.name) GROUP BY c.country
)
SELECT DISTINCT c.country, COALESCE(b.value, 0) AS buyer, COALESCE(s.value, 0) AS seller
FROM companies AS c
LEFT JOIN sold AS s ON (c.country = s.country)
LEFT JOIN buyed AS b ON (c.country = b.country)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 |