not_exists
not_exists [frame(...)]?, [predicate: bool]+
Returns rows from the primary input where the join predicate matches no row from the additional dataset at any time within the query window, using a non-temporal left anti-semijoin.
The output row type is the same as the left input: no columns are added from the right dataset. Predicate arguments must be boolean expressions; if you pass several, they are combined with logical and. Together they must reference exactly one additional dataset (for example via @other.column). Window functions are not allowed in these predicates—compute them in an upstream stage and reference the result here.
Without frame(), the right-hand side is restricted to the query window and treated as non-temporal for the join, and the result is typically not accelerable. With frame(back: …, ahead: …) from frame (using back and ahead, not start or end), both inputs must be temporal (Event, Interval, or Resource); this enables accelerable matching when the predicates themselves are accelerable. If a non-accelerable function appears inside the predicate, acceleration is disabled.
For the positive match on the same input side, use exists. To return non-matching rows from the joined dataset instead, see follow_not. For matching rows from the joined dataset, see follow. For a full relational join that adds columns, see join or leftjoin.
Categories
Accelerable
not_exists is accelerable if there is a frame() argument. A dataset that only uses accelerable verbs can be accelerated, making queries on the dataset respond faster.
Examples
not_exists user_id=@audit.user_id
Keeps session rows whose user_id never appears in the audit dataset within the query window.
not_exists frame(back:2h, ahead:15m), host=@deployments.host AND env=@deployments.env
Uses frame so a metric point is kept only when no deployment row falls within the configured temporal band around its timestamp.
Updated about 1 month ago