Estoy tratando de resolver el siguiente problema en Postgres SQL, pero no sé cómo debo construirlo. Tengo dos mesas, servicios :
ID 1 2 3y prestación_servicio :
SERVICE_ID PROVISION REQUIRED 1 A FALSE 2 B TRUE 2 C FALSE 3 B TRUE 3 C TRUELa primera parte de la consulta es fácil. Un usuario puede tener cualquier número de un conjunto de problemas. Necesito poder devolver servicios que tengan provisión para al menos uno de los problemas. Entonces esto lo hace con bastante facilidad cuando el usuario tiene problemas A y B:
select service.id from services s left join service_provision p on s.id = p.service_id where p.provision = ANY (ARRAY['A','B'])servicios de devoluciones 1,2,3
Estoy atascado en la siguiente parte: el servicio también puede tener una serie de problemas "requeridos". El usuario también debe tener todos estos problemas para que se le devuelva el servicio. Entonces, si el usuario tiene el problema 'A' y el servicio proporciona 'A', 'B' y 'B' tiene la propiedad 'requerida', entonces el servicio no debe devolverse.
El caso de prueba que quiero pasar es: problemas de usuario: ['A', 'B'] devuelve: 1,2
La estrategia en mi cabeza es hacer una segunda unión en la tabla service_provision nuevamente, colocarla en una matriz, donde luego puedo agregar una condición where para comparar esa matriz con la de búsqueda. Algo como esto:
select service.id from services s left join service_provision p on s.id = p.service_id left join service_provision p2 on s.id = p2.service_id and p2.required = true where p.provision = ANY (ARRAY['A','B']) and array_agg(p2.provision) <@ ARRAY['A','B']Mi problema es que esto no está permitido y no sé cómo solucionarlo. Cualquier idea es bienvenida...
Ya que se siente cómodo con las matrices, pruebe esto:
with inparms as ( select array['A', 'B'] as inarray ), mappings as ( select service_id, array_agg(provision) as all_provs, array_agg(provision) filter (where required) req_provs from service_provision group by service_id ) select m.* from mappings m cross join inparms i where i.inarray && all_provs and (req_provs is null or i.inarray @> req_provs); service_id | all_provs | req_provs ------------+-----------+----------- 2 | {B,C} | {B} 1 | {A} | (2 rows) inparms toma en su lista de valores de provision .
Las mappings agrupan las entradas en matrices para representar todos los valores de provision requeridos.
La comparación en la cláusula where de la consulta busca cualquier superposición con && y luego ve si req_provs es null o si req_provs está completamente contenido dentro de inarray .
Aquí hay algo simple que se acerca a lo que necesita:
select * from services s join service_provision sp where s.id in ( select service_id from service_provision req where req.required == true and req.provision in ('A', 'B') ) and sp.provision in ('A', 'B')Esto encontrará servicios con al menos una provisión requerida. Creo que desea asegurarse de que todas las disposiciones requeridas estén presentes. Tal vez pueda adaptar este enfoque de subconsulta para que coincida con lo que necesita.