SQL выбирает разные с условием

Я использую Oracle SQL.

ID | Name
----------
1     A
1     B
1     C 
2     D 
2     E
3     F

Я хочу получить столбец идентификатора, только если в поле «Имя» нет буквы A. Итак, для этого примера я бы хотел, чтобы результаты были только: 2, 3.

Как я могу этого добиться?

Я пытался:

select distinct ID
from table
where Name <> 'A'

Но это явно не сработало... Я также пробовал использовать listagg, но смог найти, как использовать в нем условие.

На будущее: 1. Всегда помечайте свои SQL-запросы своей СУБД, поскольку диалекты SQL различаются. 2. Никогда не говорите просто «это не сработало». Всегда сообщайте нам, почему это не сработало (сообщение об ошибке, слишком много строк, слишком мало строк, неправильные строки и т. д.) 3. Не вызывайте идентификатор столбца, если он не является идентификатором таблицы, который однозначно идентифицирует строку. . Хотя в вашем примере очевидно, что идентификатор — это не идентификатор, но при более сложных данных и задачах это может сильно запутать.

Thorsten Kettner 27.06.2024 09:25
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
1
76
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Используйте подзапрос с NOT IN лайком,

select distinct ID
from table
where ID NOT IN (SELECT ID FROM table WHERE Name = 'A')

Вы можете использовать этот запрос

SELECT DISTINCT ID
FROM your_table t
WHERE NOT EXISTS (
    SELECT 1
    FROM your_table t_sub
    WHERE t_sub.ID = t.ID
      AND t_sub.Name = 'A'
);

И я также создаю этот пример: https://dbfiddle.uk/nlzwmeRn

Ответ принят как подходящий

Объедините строки с помощью GROUP BY id. Затем используйте предложение HAVING, чтобы сохранять только идентификаторы, у которых нет строки «A»:

select id
from table
group by id
having count(case when name = 'A' then 1 end) = 0;

Еще один простой вариант: получить все идентификаторы за вычетом идентификаторов «A»:

select id from table
minus
select id from table where name = 'A';

Ну, есть много способов подойти к этому :-)

В хорошо построенной базе данных типичное значение повторяющегося столбца имеет родительскую таблицу (во избежание опечаток). В вашем примере это может быть что-то вроде:

CREATE TABLE groups 
(
  group_id INT,
  some_description_maybe VARCHAR(100),
  PRIMARY KEY (group_id)
);

CREATE TABLE group_letters 
(
  group_id INT, 
  letter INT,
  PRIMARY KEY (group_id, letter),
  FOREIGN KEY (group_id) REFERENCING groups (group_id)
);

И типичный запрос будет использовать предложение NOT IN или NOT EXISTS. Помните: SELECT DISTINCT очень часто является индикатором неподходящего запроса или неподходящей базы данных.

select *
from groups
where group_id not in (select group_id from group_letters where letter = 'A');

Спасибо, что приняли этот ответ. Однако я добавил комментарий о правильно построенной базе данных и ее типичном решении. Надеюсь, вы найдете это полезным.

Thorsten Kettner 27.06.2024 09:36

выбрать отдельный идентификатор из таблицы минус выбрать идентификатор из таблицы, где имя = 'A'; будет лучше

tahzibi.jafar 27.06.2024 10:26

@tahzibi.jafar: Почему? DISTINCT было бы излишним, потому что MINUSEXCEPT в стандартном SQL) по умолчанию является отдельной операцией.

Thorsten Kettner 27.06.2024 11:56

Из-за производительности (в минутах номинала). Если у нас меньше записей, МИНУС занимает меньше времени. Я знаю, что это добавляет некоторые накладные расходы при первом SELECT. в целом в больших наборах данных я думаю, что это лучше

tahzibi.jafar 27.06.2024 13:47

@tahzibi.jafar: Вы неправильно понимаете, как работает SQL. Мы говорим СУБД, что делать, а не как это делать. При любом запросе СУБД может сначала удалить дубликаты, а затем применить MINUS, или наоборот. Не пытайтесь каким-либо образом навязать СУБД. Пусть это решит. Не ставьте лишние DISTINCT в своих запросах. Это скорее помешает СУБД найти оптимальный план выполнения, чем найти его (кстати, то же самое относится и к предложениям IN.)

Thorsten Kettner 27.06.2024 16:57

Теоретически ваш аргумент верен (и мы этого желаем). Но предложение основано на некоторых моих опытах (например, подсказках SQL).

tahzibi.jafar 27.06.2024 23:50

Вы можете использовать предложение GROUP BY с HAVING, чтобы исключить те идентификаторы, у которых есть строки с именем = 'A':

SELECT id 
FROM yourtable 
GROUP BY id 
  HAVING COUNT(CASE WHEN name = 'A' THEN 1 END) = 0
ORDER BY id; --skip the ORDER BY clause if sorting is not intended

Посмотрите этот образец скрипта с вашими данными

Вы можете использовать запрос ниже. Просто замените имя таблицы

select ID
from LOCALWORK
where Name <> 'A' and 
ID <>(Select ID from LOCALWORK where NAME='A')
group by ID

Нет. Если в таблице имеется более одной строки «А», вы получите ORA-01427: Подзапрос возвращает более одной строки. Вместо этого вы можете использовать <> ALL, что довольно редко, или NOT IN, как уже предлагалось. Также редко используется GROUP BY без какой-либо функции агрегирования. В этом случае мы бы предпочли использовать DISTINCT, чтобы прояснить наше намерение.

Thorsten Kettner 27.06.2024 12:01

Понял! Спасибо. В подзапросе мы можем использовать различные, чтобы избавиться от ORA-01427.

Sumit Rajguru 27.06.2024 13:27

Нет, мы не можем. Если в подзапросе есть два разных идентификатора, после DISTINCT все равно будут два разных идентификатора.

Thorsten Kettner 27.06.2024 16:55

Существующий ответ Рохана достигает цели SQL в этом ответе.

SmellyCat 28.06.2024 04:49

Вы можете использовать этот запрос для своего вопроса.

SELECT DISTINCT id FROM table_name 
GROUP BY id 
HAVING SUM(CASE WHEN name LIKE 'A' THEN 1 else 0 end) < 1

СУММА в части HAVING будет равна 0, если идентификатор содержит букву «А» в своем имени.

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