SQL: Как выбрать только строки с уникальным значением в определенном столбце? - PullRequest
15 голосов
/ 22 октября 2008

Спасибо всем за миллион. К сожалению, ни одно из решений не работает с моей стороны, и я предполагаю, что приведенный мною пример ошибочен.

Итак, позвольте мне попробовать еще раз.

Мой стол выглядит так:

    contract    project activity
row1    1000    8000    10
row2    1000    8000    20
row3    1000    8001    10
row4    2000    9000    49
row5    2000    9001    49
row6    3000    9000    79
row7    3000    9000    78

По сути, запрос, который я ищу, вернул бы "2000,49" для "контракта, действия", потому что только контракт № 2000 имеет одно и ТОЛЬКО одно уникальное значение активности.

Опять же, заранее спасибо за миллион, boroatel

Ответы [ 12 ]

13 голосов
/ 22 октября 2008

Обновлено для использования предоставленных вами данных:

Решения с использованием исходных данных можно найти в конце этого ответа.

Используя ваши новые данные:

DECLARE  @T TABLE( [contract] INT, project INT, activity INT )
INSERT INTO @T VALUES( 1000,    8000,    10 )
INSERT INTO @T VALUES( 1000,    8000,    20 )
INSERT INTO @T VALUES( 1000,    8001,    10 )
INSERT INTO @T VALUES( 2000,    9000,    49 )
INSERT INTO @T VALUES( 2000,    9001,    49 )
INSERT INTO @T VALUES( 3000,    9000,    79 )
INSERT INTO @T VALUES( 3000,    9000,    78 )

SELECT DISTINCT [contract], activity FROM @T AS A WHERE
    (SELECT COUNT( DISTINCT activity ) 
     FROM @T AS B WHERE B.[contract] = A.[contract]) = 1

возвращает: 2000, 49

Решения с использованием исходных данных

ВНИМАНИЕ: Следующие решения используют данные, ранее приведенные в вопросе и могут не иметь смысла для текущего вопроса. Я оставил их прикрепленными только для полноты.

SELECT Col1, Count( col1 ) AS count FROM table 
GROUP BY col1
HAVING count > 1

Это должно дать вам список всех значений в столбце col1, которые не различаются. Вы можете поместить это в таблицу var или temp и присоединиться к ней.

Вот пример использования подзапроса:

DECLARE @t TABLE( col1 VARCHAR(1), col2 VARCHAR(1), col3 VARCHAR(1) )

INSERT INTO @t VALUES( 'A', 'B', 'C' );
INSERT INTO @t VALUES( 'D', 'E', 'F' );
INSERT INTO @t VALUES( 'A', 'J', 'K' );
INSERT INTO @t VALUES( 'G', 'H', 'H' );

SELECT * FROM @t

SELECT col1, col2 FROM @t WHERE col1 NOT IN 
    (SELECT col1 FROM @t AS t GROUP BY col1 HAVING COUNT( col1 ) > 1)

Возвращает:

D   E
G   H

И еще один метод, который использует временную таблицу и присоединяется:

DECLARE @t TABLE( col1 VARCHAR(1), col2 VARCHAR(1), col3 VARCHAR(1) )

INSERT INTO @t VALUES( 'A', 'B', 'C' );
INSERT INTO @t VALUES( 'D', 'E', 'F' );
INSERT INTO @t VALUES( 'A', 'J', 'K' );
INSERT INTO @t VALUES( 'G', 'H', 'H' );

SELECT * FROM @t

DROP TABLE #temp_table  
SELECT col1 INTO #temp_table
    FROM @t AS t GROUP BY col1 HAVING COUNT( col1 ) = 1

SELECT t.col1, t.col2 FROM @t AS t
    INNER JOIN #temp_table AS tt ON t.col1 = tt.col1

Также возвращает:

D   E
G   H
7 голосов
/ 22 октября 2008

Для MySQL:

SELECT contract, activity
FROM table
GROUP BY contract
HAVING COUNT(DISTINCT activity) = 1
3 голосов
/ 30 октября 2008

Я фанат НЕ СУЩЕСТВУЕТ

SELECT DISTINCT contract, activity FROM table t1
WHERE NOT EXISTS (
  SELECT * FROM table t2
  WHERE t2.contract = t1.contract AND t2.activity != t1.activity
)
2 голосов
/ 22 октября 2008

Используя возможность «динамической таблицы» в SQL Server (запрашивая запрос в круглых скобках), вы можете вернуть 2000, 49 с / ниже. Если ваша платформа не предлагает эквивалент ANSI-расширения «динамическая таблица», вы всегда можете использовать временную таблицу в двухшаговом / операторе, вставив результаты в «динамическую таблицу» во временную таблицу, а затем выполнив последующий выбор во временной таблице.

DECLARE  @T TABLE(
    [contract] INT,
    project INT,
    activity INT
)

INSERT INTO @T VALUES( 1000,    8000,    10 )
INSERT INTO @T VALUES( 1000,    8000,    20 )
INSERT INTO @T VALUES( 1000,    8001,    10 )
INSERT INTO @T VALUES( 2000,    9000,    49 )
INSERT INTO @T VALUES( 2000,    9001,    49 )
INSERT INTO @T VALUES( 3000,    9000,    79 )
INSERT INTO @T VALUES( 3000,    9000,    78 )

SELECT
    [contract],
    [Activity] =  max (activity)
FROM
    (
    SELECT
        [contract],
        [Activity]
    FROM
        @T
    GROUP BY
        [contract],
        [Activity]
    ) t
GROUP BY
    [contract]
HAVING count (*) = 1
2 голосов
/ 22 октября 2008

Попробуйте это:

select 
         contract,
        max (activity) 
from
         mytable 
group by
         contract 
having
         count (activity) = 1
2 голосов
/ 22 октября 2008

Модифицированный!

SELECT distinct contract, activity from @t a
WHERE (SELECT COUNT(DISTINCT activity) FROM @t b WHERE b.contract = a.contract) = 1

А вот еще один - короче / чище без подзапроса

select contract, max(activity) from @t
group by contract
having count(distinct activity) = 1
1 голос
/ 30 октября 2008

Извините, что вы не используете PostgreSQL ...

ВЫБЕРИТЕ ЗНАЧЕНИЕ по контракту, деятельности * Из таблицы ЗАКАЗАТЬ ПО КОНТРАКТУ, деятельность

http://www.postgresql.org/docs/8.3/static/sql-select.html#SQL-DISTINCT

Ой, подожди. Вам нужны значения только с одним ...

ВЫБРАТЬ контракт, активность, количество () Из таблицы GROUP BY контракт, вид деятельности имеет () = 1

1 голос
/ 22 октября 2008
SELECT DISTINCT Contract, Activity
FROM Contract WHERE Contract IN (
SELECT Contract 
FROM Contract
GROUP BY Contract
HAVING COUNT( DISTINCT Activity ) = 1 )
1 голос
/ 22 октября 2008

Вот еще одна опция, использующая количество серверов sql:

DECLARE  @T TABLE( [contract] INT, project INT, activity INT )
INSERT INTO @T VALUES( 1000,    8000,    10 )
INSERT INTO @T VALUES( 1000,    8000,    20 )
INSERT INTO @T VALUES( 1000,    8001,    10 )
INSERT INTO @T VALUES( 2000,    9000,    49 )
INSERT INTO @T VALUES( 2000,    9001,    49 )
INSERT INTO @T VALUES( 3000,    9000,    79 )
INSERT INTO @T VALUES( 3000,    9000,    78 )



SELECT DISTINCT [contract], activity FROM @T AS A WHERE
    (SELECT COUNT( DISTINCT activity ) 
     FROM @T AS B WHERE B.[contract] = A.[contract]) = 1
1 голос
/ 22 октября 2008

Предполагается, что ваша таблица данных называется ProjectInfo:

SELECT DISTINCT Contract, Activity
    FROM ProjectInfo
    WHERE Contract = (SELECT Contract
                          FROM (SELECT DISTINCT Contract, Activity
                                    FROM ProjectInfo) AS ContractActivities
                          GROUP BY Contract
                          HAVING COUNT(*) = 1);

Самый внутренний запрос идентифицирует контракты и действия. Следующий уровень запроса (средний) идентифицирует контракты, в которых есть только одно действие. Затем внешний запрос извлекает контракт и действие из таблицы ProjectInfo для контрактов, в которых есть одно действие.

Протестировано с использованием IBM Informix Dynamic Server 11.50 - должно работать и в других местах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...