I have the following table (example):
ID |LOCATION|DAY
1 | 1 |20190301
1 | 2 |20190301
1 | 3 |20190301
1 | 1 |20190302
1 | 4 |20190302
1 | 4 |20190305
1 | 5 |20190302
2 | 4 |20190301
2 | 1 |20190301
2 | 3 |20190303
2 | 2 |20190305
where ID is car number, Location is location id, and time is YYYYMMDD. I would like to write a SQL query to count the number for ''pair-wise locations'' for each carID in each month(YYYYMM): how many times the car existed in location i and j. That is, the final results should look like
ID|LOCATION 1|LOCATION 2|MONTH |count1|count 2
1 | 1 |2 |201903| 2 | 1
1 | 1 |3 |201903| 2 | 1
1 | 1 |4 |201903| 2 | 2
1 | 1 |5 |201903| 2 | 1
1 | 2 |3 |201903| 1 | 1
1 | 2 |4 |201903| 1 | 2
where count1 is the count for location 1 and count2 is the count for location 2, and we construct this for every pair of location1 and location2.
To construct the pairs, I tried:
Select n1.location, n2.location
From
(
Select location
from table
) n1,
(
Select location
from table
) n2
Where n1.location < n2.location
Order by n1.location, n2.location
but I would like to count the number for each location (count1, count2) instead of count for pairs.
Can I do this in sub-query in SQL? Any advice would be appreciated.
This is an odd request. You are looking for independent counts of the two locations, but aligned in one row (it is odd because there is lots of repeated data).
You can do this by aggregated before joining:
with l as (
select l.id, l.location, date_format(l.time, '%Y%m') as yyyymm,
count(*) as cnt
from carlocations l
group by l.id, l.location, date_format(l.time, '%Y%m')
)
select l1.id, l1.location as location1, l2.location2, l1.yyyymm, l1.cnt as cnt2, l2.cnt as cnt2
from l l1 join
l l2
on l1.id = l2.id and l1.yyyymm = l2.yyyymm and
l1.location < l2.location;
The with is supported in MySQL 8+. In earlier versions, you would need to repeat the subquery in the from clause.
EDIT:
Without CTEs, this looks like:
select l1.id, l1.location as location1, l2.location2, l1.yyyymm, l1.cnt as cnt2, l2.cnt as cnt2
from (select l.id, l.location, date_format(l.time, '%Y%m') as yyyymm,
count(*) as cnt
from carlocations l
group by l.id, l.location, date_format(l.time, '%Y%m')
) l1 join
(select l.id, l.location, date_format(l.time, '%Y%m') as yyyymm,
count(*) as cnt
from carlocations l
group by l.id, l.location, date_format(l.time, '%Y%m')
) l2
on l1.id = l2.id and l1.yyyymm = l2.yyyymm and
l1.location < l2.location;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With