我有一个用户表和他们发送的消息的另一个表,我正在尝试查找消息的平均长度和如果用户退休的消息的平均长度。如果我尝试这样做:

SELECT u.id,
AVG(LENGTH(m.body)) AS avg_msg_length,
AVG(LENGTH(CASE m.is_retired WHEN true THEN m.body ELSE NULL END)) AS avg_msg_length_retired
FROM Users u LEFT OUTER JOIN Messages m
ON u.id = m.sender_id
GROUP BY u.id;


结果,我得到的平均长度很好,但是退休人员的平均长度只是一列NULL。

如果我尝试这样做:

SELECT u.id,
AVG(LENGTH(m.body)) AS avg_msg_length,
AVG(LENGTH(CASE m.is_retired WHEN "true" THEN m.body ELSE NULL END)) AS avg_msg_length_retired
FROM Users u LEFT OUTER JOIN Messages m
ON u.id = m.sender_id
GROUP BY u.id;


我明白了


  错误1054(42S22):“字段列表”中的未知列“ true”。


我发现这非常奇怪,因为is_retired字段是varchar。

我是否在LENGTH中错误地使用了CASE WHEN?我也尝试了CASE WHEN的第二种形式:

 AVG(LENGTH(CASE WHEN m.is_retired=true THEN m.body ELSE NULL END)) AS avg_msg_length_retired


和,

AVG(LENGTH(CASE WHEN m.is_retired="true" THEN m.body ELSE NULL END)) AS avg_msg_length_retired


并获得与上述相同的结果。

最佳答案

我更喜欢length()中的case

SELECT u.id,
       AVG(LENGTH(m.body)) AS avg_msg_length,
       AVG(CASE WHEN m.is_retired = 'Y' THEN LENGTH(m.body) END) AS avg_msg_length_retired
FROM Users u LEFT OUTER JOIN
     Messages m
     ON u.id = m.sender_id
GROUP BY u.id;


'Y'应该是表示真值的任何字符或字符串。

查询的问题是您要混合使用字符表达式(is_retired)和数字表达式(true)。与类型保持一致。

例如,它的计算结果为false:

 select 'true' = true;


但这评估为true:

select 1 = true;

10-04 15:52