0

I'm working with DB2 using a "data" column containing a JSON object stored as a CLOB.

To simplify my scenario consider this (easier) example:

CREATE TABLE Students (
    StudentID INT PRIMARY KEY NOT NULL,
    Name VARCHAR(255),
    PrefMeal CLOB
);

INSERT INTO Students (StudentID, Name, PrefMeal) VALUES
(1, 'John Doe', '{"pizza":[{"id":2,"name":"Pizza Patate e Salsiccia","ingredients":["Potatoes","Mozzarella Cheese","Sausage"]}]}'),
(2, 'Jane Doe', '{"pizza":[{"id":1,"name":"Pizza Margherita","ingredients":["Tomato Sauce","Mozzarella Cheese","Oregano"]}]}'),
(3, 'Mario Rossi', '{"pizza":[{"id":2,"name":"Pizza Patate e Salsiccia","ingredients":["Potatoes","Mozzarella Cheese","Sausage"]},{"id":1,"name":"Pizza Margherita","ingredients":["Tomato Sauce","Mozzarella Cheese","Oregano"]}]}');

SELECT s.*
FROM Students s

Which of course returns all the students:

STUDENTID|NAME       |PREFMEAL                                                                                                                                                                                                       |
---------+-----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
        1|John Doe   |{"pizza":[{"id":2,"name":"Pizza Patate e Salsiccia","ingredients":["Potatoes","Mozzarella Cheese","Sausage"]}]}                                                                                                |
        2|Jane Doe   |{"pizza":[{"id":1,"name":"Pizza Margherita","ingredients":["Tomato Sauce","Mozzarella Cheese","Oregano"]}]}                                                                                                    |
        3|Mario Rossi|{"pizza":[{"id":2,"name":"Pizza Patate e Salsiccia","ingredients":["Potatoes","Mozzarella Cheese","Sausage"]},{"id":1,"name":"Pizza Margherita","ingredients":["Tomato Sauce","Mozzarella Cheese","Oregano"]}]}|

The Problem

Now, suppose that I would like to select all the students which have at least a "Pizza Margherita" as a prefered meal. Normally an IN operator would make the magic but $.pizza is a JSON_ARRAY and the simpler solution does not works (so json path direct access too)...

I thought that I could use JSON_QUERY function to perform something similar to:

SELECT S.NAME, JSON_QUERY(S.PREFMEAL, '$.pizza[*].name' WITH CONDITIONAL WRAPPER) AS PREF_PIZZA
FROM STUDENTS s
WHERE JSON_QUERY(S.PREFMEAL, '$.pizza[*].name') IN ('Pizza Margherita');

Which of course does not return any rows since JSON_ARRAY and IN operators works differently rather than a simpler ARRAY.

The only solution I've found so far is the following one, which of course is not feasible for some IN comparison (too expensive/long):

I don't like the only "solution" I've found so far (it's more a workaround tbh), which I think it's not feasible and too expensive in cost and length of the query (multiple values in IN would be trasformed in many OR conditions):

SELECT *
FROM STUDENTS s
WHERE (JSON_QUERY(S.PREFMEAL, '$.pizza.name' WITH CONDITIONAL WRAPPER)) LIKE ('%"Pizza Margherita"%')

That returns correctly:

STUDENTID|NAME       |PREFMEAL                                                                                                                                                                                                       |
---------+-----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
        2|Jane Doe   |{"pizza":[{"id":1,"name":"Pizza Margherita","ingredients":["Tomato Sauce","Mozzarella Cheese","Oregano"]}]}                                                                                                    |
        3|Mario Rossi|{"pizza":[{"id":2,"name":"Pizza Patate e Salsiccia","ingredients":["Potatoes","Mozzarella Cheese","Sausage"]},{"id":1,"name":"Pizza Margherita","ingredients":["Tomato Sauce","Mozzarella Cheese","Oregano"]}]}|

I'm running out of ideas, I've even tried with JSON_TABLE but can't find a way to properly use it in the Where clause. Any help will be appreciated!

5
  • Have you tried JSON_TABLE instead of JSON_QUERY? Commented Jul 22, 2024 at 12:58
  • Yup, the problem (from what I've got so far) is that you can't produce more rows for a single column value using JSON_TABLE (thus unnesting it) since you are forced to use "strict $". So the problem is almost the same. Here it's an example: SELECT S.STUDENTID, S.NAME, JT.PIZZAS FROM Students S, JSON_TABLE(S.PREFMEAL, 'strict $' COLUMNS( PIZZAS VARCHAR(100) FORMAT JSON PATH '$.pizza.name' WITH CONDITIONAL WRAPPER) ERROR ON ERROR) AS JT Which returns something like 3 Mario Rossi ["Pizza Patate e Salsiccia","Pizza Margherita"] Commented Jul 22, 2024 at 13:18
  • Check out stackoverflow.com/questions/76480819/… Commented Jul 22, 2024 at 13:41
  • Thank you Henrik, I've checked this answer but It seems not so optimized, right? I guess this is the only way but it hurts so much : / Commented Jul 22, 2024 at 15:41
  • There is a difference between SQL statement, access plan, and actual runtime. Have you tried it? I come from XML and would love to see XMLTABLE capabilities... Commented Jul 23, 2024 at 5:50

1 Answer 1

0

I just can second Henrik. A BLOB is a BLOB, and if it is 2GB in length your runtime is subobtimal. If you unnest your JSON to a table, Db2 has better methods to access the columns wanted in larger scenarios.

Sign up to request clarification or add additional context in comments.

1 Comment

After all, I agree with you guys, even because with LIKE used in that way I could not leverage on indexes so the performances could be worse. Anyway, I can't believe that for DB2 LUW JSON_TABLE does not handle unnesting (while DB2 for i-series does). Thanks for the support you all :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.