Apologize for the ugly query, but this is what my query looks like:
select "spaces"."id" as "id",
"spaces"."user_id" as "user_id",
"spaces"."type" as "type",
"spaces"."latitude" as "latitude",
"spaces"."longitude" as "longitude",
"categories"."category_id" as "categories:category_id"
from "spaces"
left join "spaces_categories" as "categories" on "categories"."space_id" =
"spaces"."id"
where "categories"."category_id" in ($)
and ST_DWithin(spaces.geometry::geography, ST_SetSRID(ST_Point($,$), 4326)::geography, $)
I am using pg 14.1
I am trying to find all spaces within a radius that meet the requested category Ids, along with all the categories for those spaces.
A space can have many category IDs, so if I search for category ids (1,2), and there happens to be 2 space results (and assume each space has 4 categories, 1,2,3,4), I would be expecting 8 rows. However, my query only returns 4 rows, for categories 1,2.
How can I update my query so I can get all the categories, as long there is some overlap?
Is it due to my IN clause?
>Solution :
And EXISTS subquery should do the trick:
SELECT s.id
, s.user_id
, s.type
, s.latitude
, s.longitude
, c.category_id AS "categories:category_id"
FROM spaces s
LEFT JOIN spaces_categories c ON c.space_id = s.id
WHERE st_dwithin(s.geometry::geography, st_setsrid(st_point($,$), 4326)::geography, $)
AND EXISTS (
SELECT FROM spaces_categories x
WHERE x.space_id = s.id
AND x.category_id IN ($)
);
There are many other ways, but this should be fastest and clearest.
The cast from geometry to geography seems worrisome for performance, though. Do you have an expression index covering that?
Related:
- How do I query all rows within a 5-mile radius of my coordinates?
- How to find intersecting geographies between two tables recursively
- Why is my spatial query slower in Postgres 13 than in Postgres 11?
- ST_DWithin Calc Meters – transform or cast?