sqlite 选择 where...and vs. case...when

Posted

技术标签:

【中文标题】sqlite 选择 where...and vs. case...when【英文标题】:sqlite select where...and vs. case...when 【发布时间】:2013-05-27 15:05:26 【问题描述】:

我是 sqlite 的新手,并且有一个填充数据库,我需要确定数据库中的任何数字生物是否具有适应度阈值水平 (fitness>=2) 并且还活着 (live=1)。我还需要排除我试图为其寻找合适伴侣的生物体的个体 ID(主键)(indivID INTEGER PRIMARY KEY)。

下面我尝试了第一行代码,但它抛出了一个 SQL 错误:

[SQLITE_ERROR] SQL 错误或缺少数据库(“CASE”附近:语法 错误)。

但是我知道错误在 SQL 语句中,因为其他函数正在成功访问数据库。

SELECT indivID FROM population CASE fitness >=2 WHEN live = 1 AND indivID!=[specific individual] ELSE NULL END

我已经尝试了下一行代码,它有效,但没有正确排除特定个人的 indivID:

SELECT [some column names] FROM [a database] WHERE fitness>=2 AND live=1 AND indivID!=[specific individual]

我有三个问题:

1) 我在上述陈述中的错误在哪里

2) 使用“case...when”和“where...and”语句有什么区别

3) 在这些查询中,可能甚至很可能没有具有足够高适应度(高于 2)的“live=1”个体有资格使用 select 语句,因此这两个查询的结果也是如此没有可行的个体(如果写得正确)则为空?

提前感谢您的帮助!

【问题讨论】:

您的第二个查询似乎很好。能否请您扩展一下‘没有正确排除特定个人的indivID’部分? 谢谢大家! @AndriyM在我重置数据库以使每个人的适应度为零并且我将一个人的适应度提高到2以便系统查询适合的伴侣(另一个适应度> = 2的人)的情况下,它报告说有一个,当我知道所有其他人都为零时。 如果只有一行与条件匹配,并且您指定要排除它的 ID,但查询仍然返回它,那么是的,我可以看到人们会对此感到困惑。但是你确定你没有犯错吗?也许排除的 ID 是错误的(因此服务器没有排除任何内容并返回唯一匹配的行)? Here's a simple example 匹配,我想,你描述的情况,我看不出有问题(查询没有按预期返回行)。您能否同样设置一个说明问题的测试用例? 【参考方案1】:

根据您的第一个查询,您似乎误解了case when 的用法。这就像一个单一值的if。它通常用于根据某些列值获取所需的值,例如

SELECT CASE WHEN col>0 THEN 1 ELSE 0 END FROM table

但它也可以用于一些漂亮的条件,例如

SELECT col FROM table WHERE CASE WHEN some_param = 1 THEN col2 = 1 ELSE true END

如果某个输入参数为 1,则此语句为 col2 = 1 的行检索列 col,如果输入参数不是 1,则检索所有行。

使用WHERE ... AND 检查条件,例如

SELECT col FROM table WHERE col>0 AND col2=0

在您的情况下,如果未找到匹配值,您将尝试选择 null。我不认为这是处理它的正确方法。您应该尝试选择您要查找的内容,然后检查是否有任何行返回。你基本上会得到这样的东西:

ResultSet rs = stmt.executeQuery("SELECT [some column names] FROM [a database] WHERE fitness>=2 AND live=1 AND indivID!=[specific individual]");
if(rs.first()) 
    //You have some data - loop over the resultset and retrieve it

else 
    //There are no matches to your query

如果您只想要一个匹配,那么您可以将其简化为

ResultSet rs = stmt.executeQuery("SELECT [some column names] FROM [a database] WHERE fitness>=2 AND live=1 AND indivID!=[specific individual] LIMIT 1");
String name = rs.first() ? rs.getString(1) : null;

请注意,我使用索引 1 表示 getString - 但它可能是您需要的任何东西。

编辑:如果您正在处理 SQLite,那么您有一个单向可移动的结果集,因此您需要稍微更改上面的代码:

ResultSet rs = stmt.executeQuery("SELECT [some column names] FROM [a database] WHERE fitness>=2 AND live=1 AND indivID!=[specific individual]");
if(!rs.isBeforeFirst()) 
    //You have some data - loop over the resultset and retrieve it

else 
    //There are no matches to your query

相应地,

ResultSet rs = stmt.executeQuery("SELECT [some column names] FROM [a database] WHERE fitness>=2 AND live=1 AND indivID!=[specific individual] LIMIT 1");
String name = !rs.isBeforeFirst() ? null : rs.getString(1) : null;;

注意rs.first()!rs.isBeforeFirst() 的变化以及条件的反转。

【讨论】:

谢谢!我已经尝试了这两种解决方案,并且在使用 rs.first() 的行上都得到了 SQL Exception: ResultSet is TYPE_FORWARD_ONLY。从网上看,我看到异常意味着我只能向前遍历结果集,那么为什么要求 first() 会产生该结果? 我发现this 在上面的评论中使用 TYPE_FORWARD 回答了我的问题。它使用if (!rs.isBeforeFirst() )(条件结果反转)而不是if (rs.first())。但是,现在我有一个错误说数据库已锁定。 修复了锁定问题---我忘记注释掉之前的一段测试代码了。 @Alex G 非常感谢您的澄清和帮助——它已经启动并运行了!

以上是关于sqlite 选择 where...and vs. case...when的主要内容,如果未能解决你的问题,请参考以下文章

带有 WHERE、AND 和 OR 的 SQL 选择语句

iOS 数据库比较:SQLite vs Core Data vs Realm

SQL选择语句与WHERE,AND,OR

关系数据库比较:SQLite vs MySQL vs PostgreSQL

JSON文件VS SQLite android

MySQL select join where AND where