It was hard, but I found a solution.
As you cannot change the structure of the data stored, a possible solution could be something like this (replace yourTable with the right name):
SELECT
yourTable.saleID AS 'Sale ID',
yourTable.amount as 'Amount',
IFNULL(
JSON_EXTRACT(newJSON, '$.Handling_Charges'), 0
) AS 'Handling Charges',
IFNULL(
JSON_EXTRACT(newJSON, '$.Packing_Charges'), 0
) AS 'Packing Charges',
IFNULL(
JSON_EXTRACT(newJSON, '$.Transportation_Charges'), 0
) AS 'Transportation Charges'
FROM yourTable,
(
SELECT saleID, CONCAT('{', GROUP_CONCAT(jsonText SEPARATOR ','), '}') AS newJSON
FROM (
SELECT saleID,
CONCAT('"', REPLACE(keyVal, ' ', '_'), '"', ': ',
IF(JSON_EXTRACT(extra_charges, CONCAT('$[0].key')) = keyVal,
JSON_EXTRACT(
extra_charges,
CONCAT('$[0].amount')
),
IF(JSON_EXTRACT(extra_charges, CONCAT('$[1].key')) = keyVal,
JSON_EXTRACT(
extra_charges,
CONCAT('$[1].amount')
),
IF(JSON_EXTRACT(extra_charges, CONCAT('$[2].key')) = keyVal,
JSON_EXTRACT(
extra_charges,
CONCAT('$[2].amount')
),
0
)
)
)) AS jsonText
FROM spr_lead
JOIN (
SELECT 'Handling Charges' AS keyVal UNION
SELECT 'Transportation Charges' AS keyVal UNION
SELECT 'Packing Charges' AS keyVal
) AS `keys`
) AS auxTable
GROUP BY saleID
) AS newJson
WHERE newJson.saleID = yourTable.saleID
This query is composed by three nested queries that are explained below:
The innermost query
SELECT
saleID,
CONCAT('"', REPLACE(keyVal, ' ', '_'), '"', ': ',
IF(JSON_EXTRACT(extra_charges, CONCAT('$[0].key')) = keyVal,
JSON_EXTRACT(
extra_charges,
CONCAT('$[0].amount')
),
IF(JSON_EXTRACT(extra_charges, CONCAT('$[1].key')) = keyVal,
JSON_EXTRACT(
extra_charges,
CONCAT('$[1].amount')
),
IF(JSON_EXTRACT(extra_charges, CONCAT('$[2].key')) = keyVal,
JSON_EXTRACT(
extra_charges,
CONCAT('$[2].amount')
),
0
)
)
)) AS jsonText
FROM spr_lead
JOIN (
SELECT 'Handling Charges' AS keyVal UNION
SELECT 'Transportation Charges' AS keyVal UNION
SELECT 'Packing Charges' AS keyVal
) AS `keys`
) AS auxTable
It gets the JSON field and creates a string with structure "key": value
replacing the spaces in the key with a '_'. It will return something like this:
saleID |
jsonText |
123 |
'"Handling_Charges": 20' |
123 |
'"Transportation_Charges": 0' |
123 |
'"Packing_Charges": 15' |
345 |
'"Handling_Charges": 0' |
345 |
'"Transportation_Charges": 10' |
345 |
'"Packing_Charges": 0' |
... |
... |
The middle query
This query joins all the strings created by the innermost query to create a new JSON string grouping them by ID:
SELECT saleID, CONCAT('{', GROUP_CONCAT(jsonText SEPARATOR ','), '}') AS newJSON
FROM (
... #the innermost query
) AS auxTable
GROUP BY saleID
) AS newJson
It returns something like this:
saleID |
newJSON |
123 |
'{"Handling_Charges": 0,"Transportation_Charges": 0,"Packing_Charges": 0}' |
345 |
'{"Handling_Charges": 0,"Transportation_Charges": 10,"Packing_Charges": 0}' |
... |
... |
The outter query
And finally, the outter query extracts the JSON data using JSON_EXTRACT and returns the expected output.