【发布时间】:2020-12-11 07:42:51
【问题描述】:
【问题讨论】:
-
您要识别多于 1 组的记录吗?还是只想输出只有 1 组的有效记录?
-
查看stackoverflow.com/questions/28717868/…。对于类似的问题,有几种解决方案。
-
我想获取多个属性设置为 Y 的记录列表。
标签: sql sql-server tsql
【问题讨论】:
标签: sql sql-server tsql
您可以使用以下布尔表达式来限制属性中最多一个“Y”值:
IIF(Attribute1 = 'Y', 1, 0) +
IIF(Attribute2 = 'Y', 1, 0) +
IIF(Attribute3 = 'Y', 1, 0) +
IIF(Attribute4 = 'Y', 1, 0) <= 1
【讨论】:
<= 1 不符合您的问题要求。令人惊讶的是你接受了这个。
你可以在这里使用连接技巧:
SELECT *
FROM yourTable
WHERE Attribute1 + Attribute2 + Attribute3 + Attribute4
NOT LIKE '%Y%Y%';
但这也将匹配具有所有 4 个属性的 N 的记录。如果你也想坚持一个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'))
【讨论】:
在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”而不超过 2 个“N”或其他任何内容。
【讨论】: