Фильтровать записи с несколькими столбцами

В таблице есть 4 атрибута. Только один атрибут может быть установлен на Y одновременно. Есть ли функция SQL Server, чтобы найти это.

Вы хотите идентифицировать записи, которые имеют более 1 набора? Или вы хотите выводить только действительные записи, которые имеют только 1 набор?

Chad Baldwin 11.12.2020 08:47

Проверьте это stackoverflow.com/questions/28717868/…. Есть пара решений похожей проблемы.

Damian Kobak 11.12.2020 08:52

Я хочу получить список записей, для которых установлено более одного атрибута Y.

Sivabalanarayanan L 11.12.2020 18:26
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
3
185
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Здесь вы можете использовать трюк конкатенации:

SELECT *
FROM yourTable
WHERE Attribute1 + Attribute2 + Attribute3 + Attribute4
      NOT LIKE '%Y%Y%';

Но это также будет соответствовать записи, имеющей N для всех 4 атрибутов. Если вы тоже хотите настаивать на одном Y, но не более одного Y, то используйте такой вариант:

SELECT *
FROM yourTable
WHERE
    Attribute1 + Attribute2 + Attribute3 + Attribute4 LIKE '%Y%' AND
    Attribute1 + Attribute2 + Attribute3 + Attribute4
      NOT LIKE '%Y%Y%';

Если вы просто хотите идентифицировать записи как «Действительные» или «Недействительные», вы можете сделать что-то вроде этого:

IF OBJECT_ID('tempdb..#Sample','U') IS NOT NULL DROP TABLE #Sample; --SELECT * FROM #Sample
CREATE TABLE #Sample (
    Attribute1 char(1) NOT NULL,
    Attribute2 char(1) NOT NULL,
    Attribute3 char(1) NOT NULL,
    Attribute4 char(1) NOT NULL
)

INSERT INTO #Sample (Attribute1, Attribute2, Attribute3, Attribute4)
VALUES ('Y','N','N','N')
    ,  ('N','Y','N','N')
    ,  ('N','N','Y','N')
    ,  ('N','N','N','Y')
    ,  ('N','N','Y','Y')

SELECT *
    , IsValid = IIF(LEN(REPLACE(CONCAT(s.Attribute1, s.Attribute2, s.Attribute3, s.Attribute4),'Y','')) >= 3, 'Valid', 'Invalid')
FROM #Sample s

Возвращает:

| Attribute1 | Attribute2 | Attribute3 | Attribute4 | IsValid | 
|------------|------------|------------|------------|---------| 
| Y          | N          | N          | N          | Valid   | 
| N          | Y          | N          | N          | Valid   | 
| N          | N          | Y          | N          | Valid   | 
| N          | N          | N          | Y          | Valid   | 
| N          | N          | Y          | Y          | Invalid | 

Логика такова... Возьмите 4 столбца и объедините их в одну строку, чтобы Y,N,N,N стало YNNN. Затем замените все экземпляры буквы «Y» и получите длину результата. Поскольку вы знаете, что первоначальная длина была равна 4, теперь вы знаете, сколько Y было удалено.

Это классический прием для подсчета количества раз, когда одна строка встречается в другой строке.

В моем примере я считаю действительным ноль или один Y.

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

DECLARE @Attr TABLE(A1 CHAR,
A2 CHAR,
A3 CHAR,
A4 CHAR)

insert Into @Attr  VALUES('Y','N','N','N')
insert Into @Attr  VALUES('N','Y','N','N')
insert Into @Attr  VALUES('N','N','Y','N')
insert Into @Attr  VALUES('N','N','N','Y')
insert Into @Attr  VALUES('Y','N','Y','N')

SELECT * FROm @Attr

SELECT * FROM @Attr
WHERE 
((A2<>'Y' AND A3<>'Y' AND A4<>'Y' ) OR 
(A1<>'Y' AND A3<>'Y' AND A4<>'Y') OR 
(A1<>'Y' AND A2<>'Y' AND A4<>'Y') OR
(A1<>'Y' AND A2<>'Y' AND A3<>'Y'))
Ответ принят как подходящий

Вы можете использовать следующее логическое выражение, чтобы ограничить не более одного значения "Y" среди атрибутов:

IIF(Attribute1 = 'Y', 1, 0) +
IIF(Attribute2 = 'Y', 1, 0) +
IIF(Attribute3 = 'Y', 1, 0) +
IIF(Attribute4 = 'Y', 1, 0) <= 1

@sivabalanarayanan . . . <= 1 не соответствует требованиям вашего вопроса. Удивительно, что ты принял это.

Gordon Linoff 11.12.2020 14:54

Удивительно, что мы оба одновременно смотрим на этот многочасовой вопрос.

Tim Biegeleisen 11.12.2020 14:55

@GordonLinoff Это работает, когда я изменил условие на него> 1. Можно было не заметить это. Я согласился, когда думал об операторах CASE, а IFF — это сокращение от CASE.

Sivabalanarayanan L 11.12.2020 18:24

В запросе select (который кажется достаточным для ваших целей) я бы рекомендовал:

select t.*
from t cross apply
     (select count(*) as num_ys
      from (values (attribute1), (attribute2), (attribute3), (attribute4)
           ) v(attr)
      where attr = 1
     ) v
where num_ys = 1;

Производительность apply в этом случае на самом деле неплохая. Что еще более важно, это значительно упрощает обобщение запроса — добавление новых атрибутов или произнесение хотя бы одного «Y» и не более двух «N» или что-то еще.

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