SQL: как ВЫБРАТЬ только строки с уникальным значением в определенном столбце?

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

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

Моя таблица выглядит так:

    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 имеет одно и ТОЛЬКО одно уникальное значение действия.

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

Что такое ПК для этой таблицы?

Walter Mitty 14.06.2011 17:43
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
17
1
110 229
12

Ответы 12

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

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

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

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 table и присоединиться к ней.

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

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

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

Jonathan Leffler 22.10.2008 07:15

Да, спрашивающий изменил вопрос и использовал другой набор данных. Приведенные выше ответы были полными с предоставленным набором данных. Я обновил ответ, чтобы отразить это, и добавил решение с использованием нового набора данных.

vfilby 22.10.2008 07:39

Для MySQL:

SELECT contract, activity
FROM table
GROUP BY contract
HAVING COUNT(DISTINCT activity) = 1

Это также не работает, у вас не может быть столбцов в списке выбора, которые не входят в GROUP BY или агрегат. Вам придется использовать тот же принцип, но во вспомогательном запросе или присоединении.

vfilby 22.10.2008 06:26

Мое плохое, это ограничение SQL Server. Я не понимал, что MySQL может иметь элементы в списке выбора, которые не были агрегатной функцией или в группе по. Извини друг.

vfilby 22.10.2008 07:45

Изменено!

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

При тестировании в IBM Informix Dynamic Server 11.50 он не выдает данных. Проблема в том, что в контракте 2000 есть две строки проекта с одинаковым кодом активности, поэтому COUNT (*) возвращает 2, а не 1.

Jonathan Leffler 22.10.2008 07:13

@Jonathan: вопрос касается Microsoft SQL Server, поэтому реализация SQL в Informix здесь совершенно неуместна.

Milan Babuškov 22.10.2008 09:54

Верно, что IDS не имеет прямого отношения, но это допустимая реализация SQL, и приведенный выше SQL выполняется, но не дает правильного ответа.

Jonathan Leffler 22.10.2008 20:29

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

select 
         contract,
        max (activity) 
from
         mytable 
group by
         contract 
having
         count (activity) = 1

При тестировании в IBM Informix Dynamic Server 11.50 это не дает ни данных, ни строки с 2000,49, как требуется. Проблема в том, что в контракте 2000 есть две строки проекта с одинаковым кодом активности, поэтому count (activity) = 2, а не 1, как требуется.

Jonathan Leffler 22.10.2008 07:10

Это не работает в SQL Server 2005. Проблема в том, что для 2000,49 есть две строки. Вам нужно считать только отдельные виды деятельности.

vfilby 22.10.2008 15:42

В свете этих комментариев см. Ответ Джетсона.

Walter Mitty 14.06.2011 17:47

Предполагая, что ваша таблица данных называется 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 - должно работать и в другом месте.

Вот еще один вариант использования подсчета серверов 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
SELECT DISTINCT Contract, Activity
FROM Contract WHERE Contract IN (
SELECT Contract 
FROM Contract
GROUP BY Contract
HAVING COUNT( DISTINCT Activity ) = 1 )

Используя возможность "динамической таблицы" в 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

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

ВЫБЕРИТЕ РАЗЛИЧИЕ ПО контракту, деятельности * Со стола ЗАКАЗАТЬ договор, деятельность

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

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

ВЫБЕРИТЕ контракт, активность, количество () ИЗ таблицы GROUP BY контракта, активность HAVING count () = 1

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

SELECT DISTINCT contract, activity FROM table t1
WHERE NOT EXISTS (
  SELECT * FROM table t2
  WHERE t2.contract = t1.contract AND t2.activity != t1.activity
)

Извините, старый пост, который я знаю, но у меня была такая же проблема, я не мог заставить что-либо из вышеперечисленного работать для меня, однако я понял это.

Это сработало для меня:

ВЫБЕРИТЕ DISTINCT [столбец] как уникальные значения ОТ [db]. [Dbo]. [Table]

ВЫБРАТЬ DISTINCT Col1, Col2 ИЗ ГРУППЫ таблиц ПО Col1, ИМЕЮЩИЕ СЧЕТ (DISTINCT Col1) = 1

Другие вопросы по теме