diff --git a/doc/sql/query.ebnf b/doc/sql/query.ebnf
index 59ab32959bb7f1670096c1579c7cb05dcf7cd79a..ff923d08fdf3ea2a15fdd57986bfc76b1ee50e34 100644
--- a/doc/sql/query.ebnf
+++ b/doc/sql/query.ebnf
@@ -41,7 +41,7 @@ expression  ::= (table '.')? column
                | 'TO_DATE' '(' expression',' format ')'
                | 'TO_CHAR' '(' expression',' format ')'
                | 'TRIM' '(' ((('LEADING' | 'TRAILING' | 'BOTH')? expression) | ('LEADING' | 'TRAILING' | 'BOTH')) 'FROM' expression ')'
-               | 'CASE' expression? ('WHEN' expression 'THEN' expression)* ('ELSE' expression)? 'END'
+               | 'CASE' expression? ('WHEN' expression 'THEN' expression)+ ('ELSE' expression)? 'END'
 aggregate   ::= ('AVG' | 'COUNT' | 'MAX' | 'MIN' | 'SUM' | 'TOTAL') '(' expression ')'
                | 'GROUP_CONCAT' '(' expression ','  "'" string "'" ')'
 cast        ::= 'CAST' '(' expression 'AS' type ')'
diff --git a/sbroad-cartridge/test_app/test/integration/arbitrary_expressions_test.lua b/sbroad-cartridge/test_app/test/integration/arbitrary_expressions_test.lua
index 9d161672ddb690c90cd7d147373f7a1ffe030d46..011a80b6aeb30de7c8a0bb17daf658add07660f2 100644
--- a/sbroad-cartridge/test_app/test/integration/arbitrary_expressions_test.lua
+++ b/sbroad-cartridge/test_app/test/integration/arbitrary_expressions_test.lua
@@ -210,6 +210,50 @@ arbitrary_projection.test_arbitrary_valid = function()
         },
     })
 
+    local r, err = api:call("sbroad.execute", { [[
+        SELECT
+            "id",
+            "val",
+            CASE "id"
+                WHEN 5 THEN 'five'
+                WHEN "val" THEN 'equal'
+            END "case_result"
+        FROM "arithmetic_space"
+        INNER JOIN
+        (SELECT "COLUMN_2" as "val" FROM (VALUES (1), (2))) AS "values"
+        ON true
+    ]], {} })
+    t.assert_equals(err, nil)
+    t.assert_equals(r, {
+        metadata = {
+            { name = "arithmetic_space.id", type = "integer"},
+            { name = "values.val", type = "any"},
+            { name = "case_result", type = "any"},
+        },
+        rows = {
+            {1, 1, 'equal'},
+            {5, 1, 'five'},
+            {8, 1, box.NULL},
+            {9, 1, box.NULL},
+            {10, 1, box.NULL},
+            {1, 2, box.NULL},
+            {5, 2, 'five'},
+            {8, 2, box.NULL},
+            {9, 2, box.NULL},
+            {10, 2, box.NULL},
+            {2, 1, box.NULL},
+            {3, 1, box.NULL},
+            {4, 1, box.NULL},
+            {6, 1, box.NULL},
+            {7, 1, box.NULL},
+            {2, 2, 'equal'},
+            {3, 2, box.NULL},
+            {4, 2, box.NULL},
+            {6, 2, box.NULL},
+            {7, 2, box.NULL},
+        },
+    })
+
     local r, err = api:call("sbroad.execute", { [[
         SELECT
             "id",
@@ -238,4 +282,40 @@ arbitrary_projection.test_arbitrary_valid = function()
             {7, 'first'},
         },
     })
+
+    local r, err = api:call("sbroad.execute", { [[
+        SELECT
+            "id",
+            CASE
+                WHEN false THEN 'never'
+                WHEN "id" < 3 THEN 1
+                WHEN "id" > 3 AND "id" < 8 THEN 2
+                ELSE
+                    CASE
+                        WHEN "id" = 8 THEN 3
+                        WHEN "id" = 9 THEN 4
+                        ELSE 0.42
+                    END
+            END
+        FROM "arithmetic_space"
+    ]], {} })
+    t.assert_equals(err, nil)
+    t.assert_equals(r, {
+        metadata = {
+            {name = "id", type = "integer"},
+            {name = "COL_1", type = "any"},
+        },
+        rows = {
+            {1, 1},
+            {5, 2},
+            {8, 3},
+            {9, 4},
+            {10, 0.42},
+            {2, 1},
+            {3, 0.42},
+            {4, 2},
+            {6, 2},
+            {7, 2},
+        },
+    })
 end
diff --git a/sbroad-core/src/frontend/sql/ir.rs b/sbroad-core/src/frontend/sql/ir.rs
index df844245082dda11583103064f113d327bbbd870..24ce1df6026cfc5f8ec8607cc4eed212783744cb 100644
--- a/sbroad-core/src/frontend/sql/ir.rs
+++ b/sbroad-core/src/frontend/sql/ir.rs
@@ -367,21 +367,21 @@ impl Plan {
                 } => {
                     if let Some(search_expr) = search_expr {
                         *search_expr = *map.get(search_expr).unwrap_or_else(|| {
-                            panic!("Search expr not found for subtree cloning.")
+                            panic!("Search expression not found for subtree cloning.")
                         });
                     }
                     for (cond_expr, res_expr) in when_blocks {
-                        *cond_expr = *map
-                            .get(cond_expr)
-                            .unwrap_or_else(|| panic!("Cond expr not found for subtree cloning."));
-                        *res_expr = *map
-                            .get(res_expr)
-                            .unwrap_or_else(|| panic!("Res expr not found for subtree cloning."));
+                        *cond_expr = *map.get(cond_expr).unwrap_or_else(|| {
+                            panic!("Condition expression not found for subtree cloning.")
+                        });
+                        *res_expr = *map.get(res_expr).unwrap_or_else(|| {
+                            panic!("Result expression not found for subtree cloning.")
+                        });
                     }
                     if let Some(else_expr) = else_expr {
-                        *else_expr = *map
-                            .get(else_expr)
-                            .unwrap_or_else(|| panic!("Else expr not found for subtree cloning."));
+                        *else_expr = *map.get(else_expr).unwrap_or_else(|| {
+                            panic!("Else expression not found for subtree cloning.")
+                        });
                     }
                 }
             }
diff --git a/sbroad-core/src/ir/expression/types.rs b/sbroad-core/src/ir/expression/types.rs
index 4a37858d38e2ea82fb5754363929e2828d337cd6..deaa1c89dcfdaaa9d5b380ef93efe6a146eba599 100644
--- a/sbroad-core/src/ir/expression/types.rs
+++ b/sbroad-core/src/ir/expression/types.rs
@@ -50,16 +50,24 @@ impl Expression {
                 ..
             } => {
                 let mut case_type = None;
+                let check_types_corresponds = |case_type: &Type, ret_expr_type: &Type| {
+                    if case_type != ret_expr_type {
+                        return if matches!(ret_expr_type, Type::Array)
+                            || matches!(ret_expr_type, Type::Map)
+                        {
+                            Some(Type::Any)
+                        } else {
+                            Some(Type::Scalar)
+                        };
+                    }
+                    None
+                };
+
                 for (_, ret_expr) in when_blocks {
                     let ret_expr_type = plan.get_node_type(*ret_expr)?;
                     if let Some(case_type) = &case_type {
-                        if case_type != &ret_expr_type {
-                            if matches!(ret_expr_type, Type::Array)
-                                || matches!(ret_expr_type, Type::Map)
-                            {
-                                return Ok(Type::Any);
-                            }
-                            return Ok(Type::Scalar);
+                        if let Some(ret_type) = check_types_corresponds(case_type, &ret_expr_type) {
+                            return Ok(ret_type);
                         }
                     } else {
                         case_type = Some(ret_expr_type);
@@ -68,13 +76,10 @@ impl Expression {
                 let case_type_unwrapped = case_type.expect("Case WHEN type must be known");
                 if let Some(else_expr) = else_expr {
                     let else_expr_type = plan.get_node_type(*else_expr)?;
-                    if case_type_unwrapped != else_expr_type {
-                        if matches!(else_expr_type, Type::Array)
-                            || matches!(else_expr_type, Type::Map)
-                        {
-                            return Ok(Type::Any);
-                        }
-                        return Ok(Type::Scalar);
+                    if let Some(ret_type) =
+                        check_types_corresponds(&case_type_unwrapped, &else_expr_type)
+                    {
+                        return Ok(ret_type);
                     }
                 }
                 Ok(case_type_unwrapped)