В таблице есть 4 атрибута. Только один атрибут может быть установлен на Y одновременно. Есть ли функция SQL Server, чтобы найти это.
Проверьте это stackoverflow.com/questions/28717868/…. Есть пара решений похожей проблемы.
Я хочу получить список записей, для которых установлено более одного атрибута Y.
Здесь вы можете использовать трюк конкатенации:
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
не соответствует требованиям вашего вопроса. Удивительно, что ты принял это.
Удивительно, что мы оба одновременно смотрим на этот многочасовой вопрос.
@GordonLinoff Это работает, когда я изменил условие на него> 1. Можно было не заметить это. Я согласился, когда думал об операторах CASE, а IFF — это сокращение от CASE.
В запросе 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» или что-то еще.
Вы хотите идентифицировать записи, которые имеют более 1 набора? Или вы хотите выводить только действительные записи, которые имеют только 1 набор?