Tenemos una tabla que usamos para almacenar las respuestas a las preguntas. Necesitamos poder encontrar usuarios que tengan ciertas respuestas a preguntas particulares. Entonces, si nuestra tabla consta de los siguientes datos:
user_id question_id answer_value
Sally 1 Pooch
Sally 2 Peach
John 1 Pooch
John 2 Duke
y queremos encontrar usuarios que respondan 'Pooch' para la pregunta 1 y 'Peach' para la pregunta 2, el siguiente SQL (obviamente) no funcionará:
select user_id
from answers
where question_id=1
and answer_value = 'Pooch'
and question_id=2
and answer_value='Peach'
Mi primer pensamiento fue unirme a la tabla para cada respuesta que buscamos:
select a.user_id
from answers a, answers b
where a.user_id = b.user_id
and a.question_id=1
and a.answer_value = 'Pooch'
and b.question_id=2
and b.answer_value='Peach'
Esto funciona, pero dado que permitimos un número arbitrario de filtros de búsqueda, necesitamos encontrar algo mucho más eficiente. Mi siguiente solución fue algo como esto:
select user_id, count(question_id)
from answers
where (
(question_id=2 and answer_value = 'Peach')
or (question_id=1 and answer_value = 'Pooch')
)
group by user_id
having count(question_id)>1
Sin embargo, queremos que los usuarios puedan tomar el mismo cuestionario dos veces, por lo que potencialmente podrían tener dos respuestas a la pregunta 1 en la tabla de respuestas.
Entonces, ahora estoy perdido. ¿Cuál es la mejor manera de abordar esto? ¡Gracias!
fuente
Me gusta el método de unión, yo mismo:
Actualización Después de probar con una tabla más grande (~ 1 millón de filas), este método tomó mucho más tiempo que el
OR
método simple mencionado en la pregunta original.fuente
Nos unimos
user_id
a laanswers
tabla en una cadena de combinaciones para obtener datos de otras tablas, pero aislar la tabla de respuestas SQL y escribirla en términos tan simples me ayudó a detectar la solución:Estábamos usando innecesariamente una segunda subconsulta.
fuente
Si tiene un gran conjunto de datos, haría dos índices:
Tendrá que unirse varias veces debido a la forma en que se organizan los datos. Si sabe qué valor para qué pregunta es menos común, puede acelerar un poco la consulta, pero el optimizador debería hacerlo por usted.
Pruebe la consulta como:
La tabla a1 debe usar el primer índice. Dependiendo de la distribución de datos, el optimizador puede usar cualquier índice. Toda la consulta debe satisfacerse a partir de los índices.
fuente
Una forma de abordarlo es obtener un subconjunto de user_id y probarlos para la segunda coincidencia:
Usando la estructura de Rolando:
Rendimientos:
fuente