Выберите отличные от нескольких полей, используя sql - PullRequest
12 голосов
/ 13 февраля 2009

У меня есть 5 столбцов, соответствующих ответам в базе данных викторины - правильно, неправильно1, неправильно2, неправильно3, неправильно4

Я хочу вернуть все возможные ответы без дубликатов. Я надеялся сделать это без использования временной таблицы. Можно ли использовать что-то похожее на это?

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

Но это возвращает 3 столбца. Я хотел бы получить один столбец четких ответов.

Спасибо за ваше время

Ответы [ 8 ]

15 голосов
/ 13 февраля 2009

Это должно дать вам все отличные значения из таблицы. Я предполагаю, что вы захотите добавить предложения where для выбора только для конкретного вопроса. Однако это решение требует 5 подзапросов и может быть медленным, если ваша таблица огромна.

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
8 голосов
/ 13 февраля 2009
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

DISTINCT является излишним, потому что UNION не будет возвращать строки, одинаковые для всех столбцов. (Если вы хотите дублировать или если вы знаете, что дубликатов не существует, используйте UNION ALL для повышения производительности)

Это даст вам единый список, содержащий все ответы. Вы все равно будете иметь дубликаты, если у вас будет несколько копий одного и того же ответа в одном столбце.

Этого не должно быть, если вы используете UNION, только если вы используете 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)
5 голосов
/ 13 февраля 2009

Я дал один ответ выше .

Однако я нашел гораздо лучший способ сделать это, используя 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;

Вы можете указать любое предложение WHERE во внутреннем подзапросе:

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;
2 голосов
/ 30 ноября 2009

Столбцы «правильно, неправильно1, неправильно2, неправильно3, неправильно4» означают, что у вас неверно спроектированная база данных. Как правило, цифра или буквенный суффикс в имени столбца должен быть красным флагом, чтобы переосмыслить проблему.

Как вы заметили, ваш дизайн требовал от вас взлома, чтобы найти решение типичной проблемы сокращения данных.

2 голосов
/ 13 февраля 2009

Ну, вы можете использовать UNION и запустить 5 операторов выбора, по одному для каждого столбца в вашей таблице. Это будет выглядеть примерно так:

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

Это даст вам единый список, содержащий все ответы. Вы все равно будете иметь дубликаты, если у вас будет несколько копий одного и того же ответа в одном столбце.

1 голос
/ 13 февраля 2009

Это то, что вы хотели?

select distinct c1 from t

0 голосов
/ 18 февраля 2009

Это точный ответ.

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 
0 голосов
/ 13 февраля 2009

В MySQL И 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

Для Oracle добавьте FROM DUAL к каждому выбранному номеру.

...