对于Firebird 3数据库,我需要相当于此Count with Case。我尝试时遇到错误:
SQL error code = -104.
Invalid usage of boolean expression.
我刚刚介绍了Case命令,我似乎无法自行修改它。我设法让它与SQLite一起使用。
目的是进行AND操作,Where不能做AND,因为关键字在行中。
SELECT Count((CASE WHEN keywords.keyword LIKE '%purchased%'
THEN 1 END) AND
(CASE WHEN keywords.keyword LIKE '%item%'
THEN 1 END)) AS TRows
FROM products
LEFT OUTER JOIN keywords_products ON
products.product_rec_id = keywords_products.product_rec_id
LEFT OUTER JOIN keywords ON
keywords_products.keyword_rec_id = keywords.keyword_rec_id
WHERE (keywords.keyword LIKE '%purchased%' OR
keywords.keyword LIKE '%item%')
我有三个SQLite表,一个产品表,一个keywords_products表和一个关键字表。
CREATE TABLE products (
product_rec_id INTEGER PRIMARY KEY NOT NULL,
name VARCHAR (100) NOT NULL
);
CREATE TABLE keywords_products (
keyword_rec_id INTEGER NOT NULL,
product_rec_id INTEGER NOT NULL
);
CREATE TABLE keywords (
keyword_rec_id INTEGER PRIMARY KEY NOT NULL,
keyword VARCHAR (50) NOT NULL UNIQUE
);
keywords_products 表包含产品的记录ID和关键字的记录ID。可以在关键字表中为每个产品分配多个关键字。
关键字表如下所示:
keyword_rec_id keyword
-------------- -----------
60 melee
43 scifi
87 water
keywords_products 表看起来像这样(一个关键字可以分配给许多产品):
keyword_rec_id product_rec_id
-------------- --------------
43 1
60 1
43 2
87 3
产品表如下所示:
product_rec_id name
-------------- --------------
1 Scifi Melee Weapons
2 Scifi Ray Weapon
3 Lake House
答案 0 :(得分:0)
您必须使用具有多个WHEN分支的单个CASE表达式。
制作不同CASE表达式的布尔函数是没有意义的 - CASE本身不是布尔函数。
您可以在https://firebirdsql.org/refdocs/langrefupd15-case.html
查看规则和示例case
when Age >= 18 then 'Yes'
when Age < 18 then 'No'
end;
在此模式之后,将两个CASE子句重写为单个CASE子句。
但是,如果无法将过滤器和条件移动到SQL select的标准部分,则只使用CASE。正常的方法是使用预过滤来最小化SQL引擎必须获取的数据。 CASE使用后过滤,它使SQL引擎获取所有数据,无论是否需要,然后丢弃不需要的获取数据。这是减缓这一过程的多余工作。
在你的情况下,你已经将条件提取到WHERE子句中,这很好。
SELECT
...
WHERE (keywords.keyword LIKE '%purchased%')
OR (keywords.keyword LIKE '%item%')
由于您预先过滤数据流以始终包含“item”或“purchase”,因此您的CASE子句将始终在此WHERE预过滤下选择的所有行上返回1。因此 - 只需删除冗余CASE子句并改为使用“1”。
SELECT Count(1)
FROM products
LEFT JOIN keywords_products ON products.product_rec_id = keywords_products.product_rec_id
LEFT JOIN keywords ON keywords_products.keyword_rec_id = keywords.keyword_rec_id
WHERE (keywords.keyword LIKE '%purchased%')
OR (keywords.keyword LIKE '%item%')
现在,假定在JOINing之后逻辑处理WHERE子句,这个查询事实上将LEFT JOIN转换为FULL JOIN(您的WHERE子句只丢弃具有NULL“关键字”列值的行)但是在不可靠且效率低下的方法中。因为你不想让“关键字是NULL”类行 - 只需将你的左连接转换为普通连接。
答案 1 :(得分:0)
我假设您想要计算两个条件均为真的行数。
发生错误是因为您无法在整数值之间使用AND
。值必须是真正的布尔值。
所以,将代码更改为
Count((CASE WHEN keywords.keyword LIKE '%purchased%'
THEN TRUE END) AND
(CASE WHEN keywords.keyword LIKE '%item%'
THEN TRUE END))
然而,这太复杂了。您可以将表达式简化为
count(nullif(
keywords.keyword LIKE '%purchased%' and keywords.keyword LIKE '%item%',
false))
需要使用NULLIF
,因为COUNT
将计算所有非NULL值(根据SQL标准的要求),false
也是非NULL。因此,为了实现(假设的)预期效果,我们使用false
将NULL
转换为NULLIF
。