Using postgres 11 I have a data table int_state
that looks like this:
dev | int |
---|---|
sw01 | gi1 |
sw01 | gi2 |
sw01 | gi3 |
sw01 | gi4 |
sw02 | gi3 |
sw02 | gi4 |
sw02 | gi5 |
sw03 | gi3 |
sw03 | gi4 |
sw03 | gi6 |
sw03 | gi7 |
I need a query that will return a single row for every instance of dev
where int
is the same across every instance of dev
. Using the sample above query should only return "gi3" as the value for int
since that value is shared between all instances of dev
and result is limited is a single row for every dev
. Desired results from sample data above:
dev | int |
---|---|
sw01 | gi3 |
sw02 | gi3 |
sw03 | gi3 |
The number of dev
instances (x) to match against will vary, but results should always contain x rows, with a row for every dev
asked for in the query. If there are multiple matches against int
the query should only return the first one found.
Using a JOIN
doesn’t seem like it will work for me, since I need x rows of results, not a single row with all results combined. I have been playing around with CTEs and UNION but so far unable to get it working. I thought nesting CTEs would help, but apparently that’s not supported in postgres.
I plan on constructing this query on-demand in code ahead of time, so if I have to construct something that contains where dev in ('sw01','sw02','x','y','z')
that’s okay.
3
Answers
You might actually get better performance if you don’t reuse the CTE on line 3, as that might trick the optimizer into thinking this is a correlated subquery rather than a constant. The core trick here is the doubly nested
WHERE NOT EXISTS
, converting "an int that appears for every dev" to the logically equivalent "an int for which there is no dev for which it does not appear."ok, so if I understand your question, you want to find all the instances of dev (01, 02, 03, etc), and then check that the value for int is the same for all the instances?
You can do a clever workaround I think….
You can build CTE with an array of distinct
dev
values and another with array ofdev
values for eachint
using array_agg. Then JOIN then on matching arrays. (see demo)