2009-02-13 11 views
12

tengo 5 columnas correspondientes a las respuestas en una base de datos de juego de preguntas - derecha, wrong1, wrong2, wrong3, wrong4Seleccionar distinta de varios campos utilizando SQL

quiero devolver todas las respuestas posibles sin duplicados. Esperaba lograr esto sin usar una tabla temporal. ¿Es posible usar algo similar a esto ?:

select c1, c2, count(*) 
from t 
group by c1, c2 

Pero esto devuelve 3 columnas. Me gustaría una columna de respuestas distintas.

Gracias por su tiempo

Respuesta

15

Esto debería darle todos los valores distintos de la tabla. Supongo que querrá agregar cláusulas Where para seleccionar solo para una pregunta en particular. Sin embargo, esta solución requiere 5 subconsultas y puede ser lenta si su tabla es enorme.

SELECT DISTINCT(ans) FROM (
    SELECT right AS ans FROM answers 
    UNION 
    SELECT wrong1 AS ans FROM answers 
    UNION 
    SELECT wrong2 AS ans FROM answers 
    UNION 
    SELECT wrong3 AS ans FROM answers 
    UNION 
    SELECT wrong4 AS ans FROM answers 
) AS Temp 
+1

esto se ve bien. Voy a tratar ahora. – Bryan

+0

Pruebe el pivote que acabo de hacer a continuación. Creo que eso es mucho mejor. Sin embargo, leería sobre qué es más eficiente, no sé demasiado sobre el funcionamiento interno de los diferentes servidores de bases de datos. – achinda99

+0

Brillante. Ojalá hubiera pensado en eso. –

1

¿Es esto lo que querías?

select distinct c1 from t

+1

Difícil de decir si lo es, pero +1 porque parece que debería estar :) –

+0

sí, es difícil de decir – JoshBerke

+0

No, eso selecciona distinto de una columna – Bryan

2

bien que se puede utilizar un UNION y correr 5 sentencias de selección, una para cada columna de la tabla. Se vería algo como esto:

SELECT right FROM answers 
UNION 
SELECT wrong1 FROM answers 
UNION 
SELECT wrong2 FROM answers 
UNION 
SELECT wrong3 FROM answers 
UNION 
SELECT wrong4 FROM answers 

Esto le dará una lista única que contiene todas las respuestas. Sin embargo, aún tendrá duplicados si tiene varias copias de la misma respuesta dentro de una sola columna.

0

En MySQL Y MS SQL:

SELECT 
     CASE 
     WHEN which = 1 THEN c1 
     WHEN which = 2 THEN c2 
     WHEN which = 3 THEN c3 
     WHEN which = 4 THEN c4 
     WHEN which = 5 THEN c5 
     END AS answer, 
     which 
FROM mytable, (
    SELECT 1 AS which 
    UNION ALL 
    SELECT 2 
    UNION ALL 
    SELECT 3 
    UNION ALL 
    SELECT 4 
    UNION ALL 
    SELECT 5 
) w 

Para Oracle, añadir FROM DUAL a cada uno del número selecciona.

5

Proporcioné una respuesta above.

Sin embargo, me pareció una forma mucho mejor de hacerlo con UNPIVOT.

SELECT DISTINCT(ans) 
FROM (
    SELECT [Name], ANS 
    FROM (
     SELECT right, wrong1, wrong2, wrong3, wrong4 
     FROM answers 
    ) AS PVT 
    UNPIVOT 
    (ans FOR [Name] IN (right, wrong1, wrong2, wrong3, wrong4)) AS UNPVT 
) AS OUTPUT; 

le puede proporcionar cualquier cláusula WHERE en la sub consulta interna:

SELECT DISTINCT(ans) 
FROM (
    SELECT [Name], ANS 
    FROM (
     SELECT right, wrong1, wrong2, wrong3, wrong4 
     FROM answers 
     WHERE (...) 
    ) AS PVT 
    UNPIVOT 
    (ans FOR [Name] IN (right, wrong1, wrong2, wrong3, wrong4)) AS UNPVT 
) AS OUTPUT; 
+0

¿por qué es esto mucho mejor? – Bryan

+0

Me gusta más esta porque lógicamente, estoy haciendo lo que quiero hacer. La primera consulta simplemente lo logra, mientras que esto sigue mi proceso de pensamiento. Además, menos selecciones secundarias. – achinda99

8
SELECT DISTINCT(ans) FROM (
    SELECT right AS ans FROM answers 
    UNION 
    SELECT wrong1 AS ans FROM answers 
    UNION 
    SELECT wrong2 AS ans FROM answers 
    UNION 
    SELECT wrong3 AS ans FROM answers 
    UNION 
    SELECT wrong4 AS ans FROM answers 
) AS Temp 

El DISTINCT es superflua, porque la Unión no volverá filas que son idénticos para todas las columnas. (Cuando se quiere duplicada, o si sabe que no existen duplicados, utilice UNION ALL para un rendimiento más rápido)

esto le dará una única lista que contiene todas las respuestas. Sin embargo, aún tendrá duplicados si tiene varias copias de la misma respuesta dentro de una sola columna.

Eso no debería ser el caso si se utiliza UNION, sólo si se utiliza UNION ALL

SELECT [value] INTO #TEMP 
FROM 
(
SELECT [value] = 1 
UNION ALL SELECT 2 
UNION ALL SELECT 3 
UNION ALL SELECT 1 
) AS X 

(4 row(s) affected) 

SELECT [value] 
FROM #TEMP 

value  
----------- 
1 
2 
3 
1 

(4 row(s) affected) 

SELECT [value] 
FROM #TEMP 
UNION 
SELECT [value] 
FROM #TEMP 

value  
----------- 
1 
2 
3 

(3 row(s) affected) 
+0

Sí, tienes razón. Estaba equivocado en eso. Probé ambos y me dio resultados similares en mi conjunto de datos, pero no estaba seguro de los detalles, por lo que si hubiera duplicados, DISTINCT se habría encargado de ello. Nunca he usado una UNIÓN en ningún trabajo real que haya hecho. Solo fines educativos. – achinda99

+0

¡Estás en lo correcto! Distinto no es necesario. – Bryan

+0

¡Sin preocupaciones! Vale la pena recordar que siempre debe usar UNION ALL cuando sepa que no hay duplicados (o QUIERE duplicados). Guarda el servidor teniendo que hacer un SORT y De-DUPE – Kristen

0

Ésta es la respuesta exacta.

SELECT (ans) FROM (
    SELECT correct AS ans FROM tGeoQuiz 
    UNION 
    SELECT wrong1 AS ans FROM tGeoQuiz 
    UNION 
    SELECT wrong2 AS ans FROM tGeoQuiz 
    UNION 
    SELECT wrong3 AS ans FROM tGeoQuiz 
    UNION 
    SELECT wrong4 AS ans FROM tGeoQuiz 
) AS Temp 
2

Columnas de "derecho, wrong1, wrong2, wrong3, wrong4" significa que usted tiene una base de datos mal diseñada. En general, un sufijo de número o letra en el nombre de una columna debe ser una bandera roja para replantear el problema.

Como observaste, tu diseño requería que hagas un corte para encontrar una solución a un problema típico de reducción de datos.

+0

Eres un tonto. Para una prueba simple, no hay nada de malo en crear una tabla rápida de preguntas. Intentando sonar más inteligente que ... somos ¿verdad? – Bryan

Cuestiones relacionadas