I have two tables practice and facility that have a one to many relationship that is established with a linking table facility_practice.
I would like a result that aggregates the "many" portion of the relationship in a json array. The following query yields the desired result:
Query
select
practice.id
, practice.name
, practice.code
, json_arrayagg(json_object(
"id", facility.id
, "name", facility.name
, "code", facility.code
)) as facility_json
from practice
left join facility_practice
on facility_practice.practice_id = practice.id
left join facility
on facility.id = facility_practice.facility_id
where practice.id = 1
group by practice.id;
Result
+----+------+-------+---------------------------------------------------------------------------------------------+
| id | name | code | facility_json |
+----+------+-------+---------------------------------------------------------------------------------------------+
| 1 | Test | NA | [{"id": 1, "code": "NA", "name": "Test"}, {"id": 15, "code": "HV", "name": "Harbour View"}] |
+----+------+-------+---------------------------------------------------------------------------------------------+
If I explain the above query, I get about what I would expect:
Explain
+----+-------------+-------------------+--------+-------------+
| id | select_type | table | type | key |
+----+-------------+-------------------+--------+-------------+
| 1 | SIMPLE | practice | const | PRIMARY |
+----+-------------+-------------------+--------+-------------+
| 1 | SIMPLE | facility_practice | ref | practice_id |
+----+-------------+-------------------+--------+-------------+
| 1 | SIMPLE | facility | eq_ref | PRIMARY |
+----+-------------+-------------------+--------+-------------+
If I then try and create a view out of that query MySQL suddenly performs a full table scan on the practice table. I have noticed that if I remove the group by portion of the query it no longer does a full table scan; however, the result is no longer correct (obviously).
View
drop view if exists practice_facility_v;
create view practice_facility_v as
select
practice.id
, practice.name
, practice.code
, json_arrayagg(json_object(
"id", facility.id
, "name", facility.name
, "code", facility.code
)) as facility_json
from practice
left join facility_practice
on facility_practice.practice_id = practice.id
left join facility
on facility.id = facility_practice.facility_id
group by practice.id;
select * from practice_facility_v where id = 1;
Explain
+----+-------------+-------------------+------------+--------+---------------+-------------+---------+-------------------------------------------+------+----------+----------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------------------+------------+--------+---------------+-------------+---------+-------------------------------------------+------+----------+----------------+
| 1 | PRIMARY | <derived2> | (NULL) | ref | <auto_key0> | <auto_key0> | 4 | const | 1 | 100.00 | |
+----+-------------+-------------------+------------+--------+---------------+-------------+---------+-------------------------------------------+------+----------+----------------+
| 2 | DERIVED | practice | (NULL) | ALL | PRIMARY | (NULL) | (NULL) | (NULL) | 7 | 100.00 | Using filesort |
+----+-------------+-------------------+------------+--------+---------------+-------------+---------+-------------------------------------------+------+----------+----------------+
| 2 | DERIVED | facility_practice | (NULL) | ref | practice_id | practice_id | 4 | ChargeBook.practice.id | 2 | 100.00 | |
+----+-------------+-------------------+------------+--------+---------------+-------------+---------+-------------------------------------------+------+----------+----------------+
| 2 | DERIVED | facility | (NULL) | eq_ref | PRIMARY | PRIMARY | 4 | ChargeBook.facility_practice.facility_id | 1 | 100.00 | |
+----+-------------+-------------------+------------+--------+---------------+-------------+---------+-------------------------------------------+------+----------+----------------+