如果我有这样的表:
CREATE TABLE `Suppression` (
`SuppressionId` int(11) NOT NULL AUTO_INCREMENT,
`Address` varchar(255) DEFAULT NULL,
`BooleanOne` bit(1) NOT NULL DEFAULT '0',
`BooleanTwo` bit(1) NOT NULL DEFAULT '0',
`BooleanThree` bit(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`SuppressionId`),
)
是否有一种基于集合的方式,我可以选择所有记录中只有三个位字段之一= 1 而不写出字段名称?
例如:
1 10 Pretend Street 1 1 1
2 11 Pretend Street 0 0 0
3 12 Pretend Street 1 1 0
4 13 Pretend Street 0 1 0
5 14 Pretend Street 1 0 1
6 14 Pretend Street 1 0 0
我想返回记录4和6.
答案 0 :(得分:3)
您可以"添加它们":
((lambda (s) (s s -1 1 0))
(lambda (hep M f! euler-number)
((lambda (s)
(if (= M 20)
(+ 0.0 euler-number)
(s s 1 1 (+ euler-number (/ 1 f!)))))
(lambda (hop N x! euler)
(hep hop (+ N 1) (* x! N) euler)))))
或者,使用元组:
where cast(booleanone as unsigned) + cast(booleantwo as unsigned) + cast(booleanthree as unsigned) = 1
我不确定你的意思是"基于集合"。
答案 1 :(得分:2)
如果布尔值的数量随着时间的推移而变化,并且您不想更新代码,我建议您将它们设为行而不是列。 例如:
CREATE TABLE `Suppression` (
`SuppressionId` int(11) NOT NULL AUTO_INCREMENT,
`Address` varchar(255) DEFAULT NULL,
`BooleanId` int(11) NOT NULL,
`BooleanValue` bit(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`SuppressionId`,`BooleanId`),
)
因此,通过1个查询和“分组依据”,您可以检查布尔值的所有值,无论它们多少。当然,这会让你的桌子更大。
编辑:刚出来另一个想法:为什么你没有添加checksum
列,其值是所有位的总和?因此,您每次写入表格时都会更新,只需在select
答案 2 :(得分:1)
如果你
然后你必须弄清楚如何编写程序来编写查询。
您可以使用此查询来检索布尔值列的结果集,然后您可以在程序中使用该结果集来编写涉及所有这些列的查询。
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'Suppression'
AND COLUMN_NAME LIKE 'Boolean%'
AND DATA_TYPE = 'bit'
AND NUMERIC_PRECISION=1
不幸的是,当您添加列时,此处提出的方法将以指数方式更加糟糕。任何时候软件工程师说"指数"现在是时候逃避尖叫了。严重。
更多可扩展的方法是在Suppression
行和标志之间建立一对多的关系。添加此表。
CREATE TABLE SuppressionFlags (
SuppressionId int(11) NOT NULL,
FlagName varchar(31) NOT NULL,
Value bit(1) NOT NULL DEFAULT '0',
PRIMARY KEY (SuppressionID, FlagName)
)
然后,当您想要插入带有一些标志变量的行时,请执行以下查询序列。
INSERT INTO Suppression (Address) VALUES ('some address');
SET @SuppressionId := LAST_INSERT_ID();
INSERT INTO SuppressionFlags (SuppressionId, FlagName, Value)
VALUES (@SuppressionId, 'BooleanOne', 1);
INSERT INTO SuppressionFlags (SuppressionId, FlagName, Value)
VALUES (@SuppressionId, 'BooleanTwo', 0);
INSERT INTO SuppressionFlags (SuppressionId, FlagName, Value)
VALUES (@SuppressionId, 'BooleanThree', 0);
这为您提供了一个Suppression
行,其中SuppressionFlags
表中设置了三个标志。请注意使用@SuppressionId
在第二个表中设置Id
值。
然后要查找只有一个标志集的所有行,请执行此操作。
SELECT Suppression.SuppressionId, Suppression.Address
FROM Suppression
JOIN SuppressionFlags ON Suppression.SuppressionId = SuppressionFlags.SuppressionId
GROUP BY Suppression.SuppressionId, Suppression.Address
HAVING SUM(SuppressionFlags.Value) = 1
如果你想要更复杂的组合,它会变得有点棘手。例如,如果您想要设置BooleanOne
和BooleanTwo
或BooleanThree
的所有行,则需要执行以下操作。
SELECT S.SuppressionId, S.Address
FROM Suppression S
JOIN SuppressionFlags A ON S.SuppressionId=A.SuppressionId AND A.FlagName='BooleanOne'
JOIN SuppressionFlags B ON S.SuppressionId=B.SuppressionId AND B.FlagName='BooleanTwo'
JOIN SuppressionFlags C ON S.SuppressionId=C.SuppressionId AND C.FlagName='BooleanThree'
WHERE A.Value = 1 AND (B.Value = 1 OR C.Value = 1)
这种常见的数据库模式称为属性/值模式。因为SQL不容易让你使用变量作为列名(它没有真正反射),这种命名属性的方式是你可扩展性的最佳途径。
它还有一点SQL。但是你可以在生产中添加任意数量的新标志,而无需重写查询或获得标志匹配的组合爆炸。并且SQL是为处理这种查询而构建的。