clickHouse查询问题

在使用clickHouse查询时报如下错误

SQL 错误 [62]: ClickHouse exception, code: 62, host: 172.16.45.35, port: 8123; Code: 62, e.displayText() = DB::Exception: Syntax error: failed at position 175

具体sql如下:

SELECT SUM(deviceState) as onlineTome from vc_device.devicehistorystatic d where 1=1
AND createTime BETWEEN '2023-06-25 00:00:00' AND '2023-07-25 23:59:59'
AND POSITION ('1ebccad6-8478-4e43-a8f3-7ecf3032415d,21e54e29-b94c-4482-904c-f6d7d6dd7182,bd4cff75-4b3f-11eb-9007-9c5c8e320598,e6f2c325-215b-48ab-898c-7914099fe661,bd4cff75-4b3f-11eb-9007-9c5c8e320573,bd4cff75-4b3f-11eb-9007-9c5c8e320826,baa9b86a-27ae-49b4-93a5-fdd38c383ed5,a866b302-659a-41df-acec-de60680875cg,e4f7f886-aee3-4d34-ae92-ae68043a34a9,460172fb-22e8-4699-a613-5f9c0f936656,bd4cff75-4b3f-11eb-9007-9c5c8e320598,bd4cff75-4b3f-11eb-9007-9c5c8e320587,b855af29-4239-4815-a4fd-19072c4af6e3,bd4cff75-4b3f-11eb-9007-9c5c8e320678,e69ab51f-96e1-4515-ae64-39c915534ead,4642ab88-3249-49e0-9e19-11d034f02d10,bd4cff75-4b3f-11eb-9007-9c5c8e320599,bd4cff75-4b3f-11eb-9007-9c5c8e320586,b77e19d1-bc73-4655-8090-f1392b45ac0a,bd4cff75-4b3f-11eb-9007-9c5c8e320677,'
;no)
其中POSITION (' str',no)中str对应30000多个参数


SELECT SUM(deviceState) as onlineTome from vc_device.devicehistorystatic d 
WHERE 1=1
AND createTime BETWEEN '2023-06-25 00:00:00' AND '2023-07-25 23:59:59'
AND some_field IN ('value1', 'value2', 'value3', ...);

你sql贴的对吗?POSITION (' str' ;no) 这里怎么是分号

猜测:
可能是 POSITION 函数的参数中包含了30000多个字符串,导致查询字符串过长,超出了 ClickHouse 的限制,从而导致语法错误
解决:
可以试着减少POSITION参数中的字符串格式,分批查询,union之后,统一计算sum

减少你的参数数量,或者修改 max_query_size 的值,默认值是 256 KB

【以下回答由 GPT 生成】

这个问题是因为在ClickHouse的SQL语句中使用了太多的参数,导致语句长度超过了ClickHouse支持的最大限制。解决这个问题的方法是使用IN运算符代替POSITION函数来处理这么多参数。下面是一个具体的解决方案:

SELECT SUM(deviceState) as onlineTome from vc_device.devicehistorystatic d where 1=1
AND createTime BETWEEN '2023-06-25 00:00:00' AND '2023-07-25 23:59:59'
AND device IN (
    '1ebccad6-8478-4e43-a8f3-7ecf3032415d',
    '21e54e29-b94c-4482-904c-f6d7d6dd7182',
    'bd4cff75-4b3f-11eb-9007-9c5c8e320598',
    'e6f2c325-215b-48ab-898c-7914099fe661',
    'bd4cff75-4b3f-11eb-9007-9c5c8e320573',
    'bd4cff75-4b3f-11eb-9007-9c5c8e320826',
    'baa9b86a-27ae-49b4-93a5-fdd38c383ed5',
    'a866b302-659a-41df-acec-de60680875cg',
    'e4f7f886-aee3-4d34-ae92-ae68043a34a9',
    '460172fb-22e8-4699-a613-5f9c0f936656',
    'bd4cff75-4b3f-11eb-9007-9c5c8e320598',
    'bd4cff75-4b3f-11eb-9007-9c5c8e320587',
    'b855af29-4239-4815-a4fd-19072c4af6e3',
    'bd4cff75-4b3f-11eb-9007-9c5c8e320678',
    'e69ab51f-96e1-4515-ae64-39c915534ead',
    '4642ab88-3249-49e0-9e19-11d034f02d10',
    'bd4cff75-4b3f-11eb-9007-9c5c8e320599',
    'bd4cff75-4b3f-11eb-9007-9c5c8e320586',
    'b77e19d1-bc73-4655-8090-f1392b45ac0a',
    'bd4cff75-4b3f-11eb-9007-9c5c8e320677'
)

将所有的参数列出并使用IN运算符将其包含在一个括号内。这样使用IN运算符可以避免参数过多导致的语句长度超过限制的问题。


如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

ClickHouse中的POSITION函数是用来查找一个字符串在另一个字符串中的位置的,而且它的参数是两个字符串。根据你提供的SQL语句和错误信息,看起来你在POSITION函数的第一个参数中传入了一个过长的字符串,可能超出了ClickHouse支持的字符串长度限制,导致出现了语法错误。

要解决这个问题,你可以考虑使用IN操作符来代替POSITION函数,从而避免将大量的参数放入单个字符串中。例如,你可以将需要查找的UUID放入一个数组中,然后使用IN操作符进行查询。以下是一个示例:

SELECT SUM(deviceState) as onlineTome 
FROM vc_device.devicehistorystatic d 
WHERE 1=1
  AND createTime BETWEEN '2023-06-25 00:00:00' AND '2023-07-25 23:59:59'
  AND deviceId IN ('1ebccad6-8478-4e43-a8f3-7ecf3032415d', '21e54e29-b94c-4482-904c-f6d7d6dd7182', ...);

注意,上述示例中的IN操作符将多个UUID放入一个数组中,每个UUID之间用逗号分隔。

如果你需要查询的UUID数量非常多,超出了SQL语句长度限制,那么可以考虑将这些UUID存放在一个临时表中,然后在查询中通过JOIN操作来实现。

最终的目标是避免将过长的字符串放入POSITION函数中,从而避免出现语法错误。

ClickHouse 的错误信息 "Syntax error: failed at position 175" 指示在 SQL 查询的第175个位置出现了语法错误。根据你提供的 SQL 查询,我看到在查询条件的最后使用了 POSITION 函数,但是在这里使用的方式是不正确的。

POSITION 函数是用来查找一个子字符串在另一个字符串中的位置,但你的使用方式似乎是错误的。你提到要查找的子字符串有30000多个参数,如果你想要检查一个字段是否包含在这个列表中,你应该使用 IN 条件。下面是你可能想要的查询修正:

SELECT SUM(deviceState) as onlineTome
FROM vc_device.devicehistorystatic d
WHERE createTime BETWEEN '2023-06-25 00:00:00' AND '2023-07-25 23:59:59'
AND deviceState IN ('1ebccad6-8478-4e43-a8f3-7ecf3032415d', '21e54e29-b94c-4482-904c-f6d7d6dd7182', ...); -- 以及其他 uuids

'1ebccad6-8478-4e43-a8f3-7ecf3032415d', '21e54e29-b94c-4482-904c-f6d7d6dd7182', ... 替换为你需要检查的UUID列表。

如果你的确需要检查一个字符串是否包含在一个长的逗号分隔的字符串中,你可以使用类似 like 的方式来进行:

SELECT SUM(deviceState) as onlineTome
FROM vc_device.devicehistorystatic d
WHERE createTime BETWEEN '2023-06-25 00:00:00' AND '2023-07-25 23:59:59'
AND '1ebccad6-8478-4e43-a8f3-7ecf3032415d,21e54e29-b94c-4482-904c-f6d7d6dd7182,...' LIKE '%' || deviceState || '%';

但是这种方式通常不是很高效,而且如果不处理好可能会导致一些逻辑错误。如果可能,建议将你的 UUID 列作为一个单独的表,然后通过 JOIN 来实现你的查询需求,这会更加有效和清晰。

ClickHouse client version 20.5.2.7 (official build).:建表语句中增加对表的COMMENT "" 会如上错误;

ClickHouse client version 21.8.3.44 (official build) 则不会报错;