How to explode a string by comma with json object - mysql

I have a problem, I have a varchar field that contains m values ​​separated by commas:
garage 1,2
garage 1,3,5
I have the following query
select
json_object(
'data',
json_objectagg(
r.slug,
json_object(
'nome',r.name,
'localizacao',
json_object(
'endereco' , r.address,
'bairro' , r.neighborhood,
'cidade' , r.city,
'estado' , r.state,
'latitude' , r.lat,
'longitude' , r.lng
),
'tipo' , r.type,
'incorporadora' , d.name,
'dormitorios', json_object('legenda', r.rooms, 'quantidade', json_array(r.rooms_quantity)),
'garagem', json_object('legenda', r.garage, 'quantidade', json_array(r.garage_quantity)),
'metragem', json_object('legenda', r.footage, 'minimo', r.min_footage, 'maximo', r.max_footage),
'preco', json_object('minimo', IFNULL(r.min_value, 0), 'maximo' , IFNULL(r.max_value, 0)),
'capa' , ri.filename_default
)
)
) as jsonExport
from realties r
inner join developers d on r.developer_id = d.developer_id
inner join realties_images ri on r.realty_id = ri.realty_id and ri.type_image = 'cover'
where r.active = 'yes' and d.active = 'yes' and ri.active = 'yes';
But when returning json_array with integers it does not match quotes.
being this ["2,Studio"] ["1,2,3"]
but I needed it to be an array because that other code will fetch the information and I needed it
["2","Studio"] ["1","2","3"]
I already tried array_objectagg and everything is something, can anyone help me?

The best solution would be to normalize the database and avoid storing multiple values in one field.
Another solution would be to retrieve the resultset and use some kind of server scripting, process it and then convert it to JSON.
You could write your own MySQL functions to explode comma separated values, e.g like this. However, my advise would be to stick with #1. It will save you time in a long term.

Related

Replace substring from an table with an stringified value of another table

So I have 2 tables and one contains an string with an ID I want to replace with an string by another table.
I came up with this SQL, which should work, but it seems like an LEFT JOIN isn't allowed in this case.
UPDATE sales_channel_api_context AS api
SET api.payload = REPLACE(
api.payload,
SUBSTRING(
api.payload,
LOCATE('paymentMethodId":"', api.payload)+18,
32
),
LOWER(HEX(c.default_payment_method_id))
)
LEFT JOIN customer AS c
ON c.id = api.customer_id
WHERE api.payload LIKE '%paymentMethodId%' AND api.customer_id IS NOT NULL;
Does anyone know an SQL Query that does exactly this, without creating another table?
An temp table can be used but an new permanent table is no solution.
ChatGPT gave me a working solution and it is as follow:
UPDATE sales_channel_api_context
JOIN customer c ON c.id = sales_channel_api_context.customer_id
SET payload =
CASE
WHEN payload LIKE '%paymentMethodId%' THEN
REPLACE(
payload,
SUBSTRING(
payload,
LOCATE('paymentMethodId":"', payload) + 18,
32
),
LOWER(HEX(c.default_payment_method_id))
)
ELSE payload
END
WHERE sales_channel_api_context.customer_id IS NOT NULL;

how to convert an object into integer array in postgress?

resp_data = array_to_json(array(
select jsonb_build_object(
'id', sp_authorities.db_id ,
'role_id', sp_authorities.role_id ,
'srvc_type_id', sp_authorities.srvc_type_id,
'form_data', sp_authorities.form_data ,
'sp_cust_fields_json',jsonb_agg(sp_orgs_settings.settings_data->'sp_cust_fields_json')
)
from public.cl_cf_srvc_prvdr_authorities as sp_authorities
left join public.cl_tx_orgs_settings as sp_orgs_settings
on sp_authorities.srvc_type_id = any(unnest(array(
SELECT json_array_elements_text(json_extract_path(sp_orgs_settings.settings_data,'srvc_type_id'::integer[])))
))
srvc_type_id array is not formed instead malformed array literal error is occuring
[enter image enter image description herehere](https://i.stack.imgur.com/2t1We.png)
To convert all the rows of a SELECT query into a single array, use the array_agg function.
SELECT array_agg(sp_authorities.srvc_type_id) ... -- Gives an array of raw integers
SELECT array_agg(json_build_object('id',sp_authorities.srvc_type_id)) ... -- Gives an array of json objects
SELECT array_to_json(array_agg ... -- Gives a json array of either of the above

Missing text from <memo> field in table in report

I have multiple models in Sparx Enterprise Architect in file-based, i.e. using MS access.
I'm using a custom template to populate a table with data from object's properties, including some with <memo> fields.
This is the query i'm using in the template fragment:
SELECT obj.object_id,
obj.Stereotype,
objp.Property as Prop,
switch(objp.Value = '<memo>', objp.Notes, objp.Value LIKE '{*}',
NULL, 1=1, objp.Value) AS Val,
(SELECT tobj2.ea_guid & tobj2.Name FROM t_object tobj2 WHERE
tobj2.ea_guid = objp.Value) AS [Obj-Hyperlink]
FROM t_object obj
INNER JOIN t_objectproperties objp
ON (obj.object_id = objp.object_id)
WHERE obj.object_id = #OBJECTID# AND obj.Stereotype='Data-
Stream' AND objp.Property NOT IN ('isEncapsulated')
ORDER BY objp.Property ASC;
I found that the when these fields are longer than 249 chars I get an error message when generating the reports and the cell in the generated table is simply empty. This is also noticeable with a query:
The error I'm getting states:
"Error Processing xml document: an invalid character was found in text context"
Is there any workarround to enable including the <memo> fields' data with more than 249 chars in the reports?
Any help is much appreciated.
I've found a workaround for this by joining two queries with a "Union all". The first query will handle the non-memo fields with the switch function and the second one the memo fields without the switch function.
select
obj.object_id,
obj.Stereotype,
objp.Property as Prop,
objp.Notes AS Val,
(
SELECT
tobj2.ea_guid & tobj2.Name
FROM
t_object tobj2
WHERE
tobj2.ea_guid = objp.Value
) AS [Obj-Hyperlink]
from
t_objectproperties objp
left join t_object obj on (obj.object_id = objp.object_ID)
where
obj.object_id = #OBJECTID#
AND obj.Stereotype = 'Data-Stream'
AND objp.Property NOT IN ('isEncapsulated')
AND objp.Value = "<memo>"
UNION ALL
SELECT
obj2.object_id,
obj2.Stereotype,
objp2.Property as Prop,
switch(
objp2.Value LIKE '{*}', NULL, 1 = 1, objp2.Value
) AS Val,
(
SELECT
tobj2.ea_guid & tobj2.Name
FROM
t_object tobj2
WHERE
tobj2.ea_guid = objp2.Value
) AS [Obj-Hyperlink]
FROM
t_object obj2
INNER JOIN t_objectproperties objp2 ON (obj2.object_id = objp2.object_id)
WHERE
obj2.object_id = #OBJECTID#
AND obj2.Stereotype = 'Data-Stream'
AND objp2.Property NOT IN ('isEncapsulated')
and objp2.Value <> "<memo>"
order by
3 asc;
Thanks a lot #geertbellekens for your comment which was crucial to find this solution.

Adding *1 to addAttributeToSort not working

I'm working within a product collection returning products and trying to order them. The problem is one of my product attributes (I find this out at 90% of the way through my project) is a quantity, i.e. 250, 5000 etc. However, I've just found out that despite these being numbers Magento treats them as strings, so therefore the collection returns the following quantities in this example:
50,100,250,500,1000,2000,5000
However, addAttributeToSort('quantity','ASC'); does this:
100,1000,2000,250,50,500,5000
I've done a var_dump() on the collection and ascertained that the values are being treated as strings, hence why this is probably happening. Unfortunately I've got over 6000 products with a lot of custom implementations and configurable products depending on this attribute, so am reluctant to change it. Searching on here I found that adding ORDER BY 'quantity' *1 does actually perform the sort correctly, however I can't seem to implement this clause in the standard addAttributeToSort function.
If anyone could help me implement this, I've tried addAttributeToSort('quantity','*1'); but that doesn't work, just errors.
Many thanks
UPDATE:
Here's the syntax for the query which is generated from the following code:
$collection = $this->getUsedProductCollection($product)
->addAttributeToSelect('*')
->addFieldToFilter('name', array( 'like' => '%' . $stock . '%' ));
$collection->getSelect()->order(new Zend_Db_Expr('quantity' *1));
count($collection);
'SELECT 'e'.*, 'link_table'.'parent_id', IF(at_name.value_id > 0, at_name.value, at_name_default.value) AS 'name', 'price_index'.'price', 'price_index'.'tax_class_id', 'price_index'.'final_price', IF(price_index.tier_price IS NOT NULL, LEAST(price_index.min_price, price_index.tier_price), price_index.min_price) AS 'minimal_price', 'price_index'.'min_price', 'price_index'.'max_price', 'price_index'.'tier_price' FROM 'catalog_product_entity' AS 'e' INNER JOIN 'catalog_product_super_link' AS 'link_table' ON link_table.product_id = e.entity_id INNER JOIN 'catalog_product_website' AS 'product_website' ON product_website.product_id = e.entity_id AND product_website.website_id = '1' INNER JOIN 'catalog_product_entity_varchar' AS 'at_name_default' ON ('at_name_default'.'entity_id' = 'e'.'entity_id') AND ('at_name_default'.'attribute_id' = '65') AND 'at_name_default'.'store_id' = 0 LEFT JOIN 'catalog_product_entity_varchar' AS 'at_name' ON ('at_name'.'entity_id' = 'e'.'entity_id') AND ('at_name'.'attribute_id' = '65') AND ('at_name'.'store_id' = 1) INNER JOIN 'catalog_product_index_price' AS 'price_index' ON price_index.entity_id = e.entity_id AND price_index.website_id = '1' AND price_index.customer_group_id = 0 WHERE (link_table.parent_id = 3781) AND (IF(at_name.value_id > 0, at_name.value, at_name_default.value) LIKE '%PCL Labels%')'
try
$collection->getSelect()->order(new Zend_Db_Expr('quantity' *1));
In the end I achieved this in PHP via ksort(). The database model when implementing any Zend functions was being overridden somewhere and I couldn't afford the time to figure it out.

how to translate a very long mysql query with select and join to zend framework 1.11 model

I have this mysql query:
SELECT
freeAnswers.*,
(SELECT `districtCode`
FROM `geodatas`
WHERE `zipCode` = clients.zipCode
GROUP BY `zipCode`
LIMIT 0, 1) as districtCode,
clients.zipCode,
clients.gender,
clients.startAge,
clients.endAge,
clients.mail,
clients.facebook,
surveys.customerId,
surveys.activityId,
surveys.name as surveyName,
customers.companyName,
activities.name as activityName
FROM freeAnswers,
clients,
surveys,
customers,
activities
WHERE freeAnswers.surveyId = surveys.id
AND surveys.customerId = customers.id
AND activities.id = surveys.activityId
AND clients.id = freeAnswers.clientId
AND customers.id = 1
ORDER BY activityName asc
LIMIT 0, 10
the query is correct on my mysql server but when I try to use it in Zend Framework 1.11 model
I get this error: Mysqli prepare error: Operand should contain 1 column(s)
Please, could anyone help me to make it run well?
Best Regards,
Elaidon
Here is some code that should work. Zend_Db_Select doesn't really provide a way to select from multiple tables in the FROM clause without using a JOIN so this feels a bit hackish to me in regards to one small part of the query. Your best bet will probably be to rewrite the query using JOINs where appropriate.
$subselect = $db->select()
->from('geodatas', 'districtCode')
->where('zipCode = clients.zipCode')
->group('zipCode')
->limit(1, 0);
$from = $db->quoteIdentifier('freeAnswers') . ', ' .
$db->quoteIdentifier('clients') . ', ' .
$db->quoteIdentifier('surveys') . ', ' .
$db->quoteIdentifier('customers') . ', ' .
$db->quoteIdentifier('activities');
$select = $db->select()
->from(array('activities' => new Zend_Db_Expr($from)),
array('freeanswers.*',
'districtCode' =>
new Zend_Db_Expr('(' . $subselect . ')'),
'clients.zipCode', 'clients.gender', 'clients.startAge',
'clients.endAge', 'clients.mail', 'clients.facebook',
'clients.customerId', 'clients.activityId',
'surveyName' => 'surveys.name', 'customers.companyName',
'activityName' => 'activities.name'))
->where('freeAnswers.surveyId = surveys.id')
->where('surveys.customerId = customers.id')
->where('activities.id = surveys.activityId')
->where('clients.id = freeAnswers.clientId')
->where('customers.id = ?', 1)
->order('activityName ASC')
->limit(10, 0);
The only reason I say it is hackish is because of the line:
->from(array('activities' => new Zend_Db_Expr($from)),
Since from() really only works with one table, I create a Zend_Db_Expr and specify the correlation as the last table name in the expression. If you don't pass a Zend_Db_Expr, it will either quote your comma separated table name incorrectly, or if you pass an array of table names, it just uses the first. When you pass a Zend_Db_Expr with no name, it defaults to use AS t which also doesn't work in your case. That is why I put it as is.
That returns the exact SQL you provided except for the last thing mentioned. Here is actually what it returns:
SELECT
`freeanswers`.*,
(SELECT `geodatas`.`districtCode`
FROM `geodatas`
WHERE (zipCode = clients.zipCode)
GROUP BY `zipCode`
LIMIT 1) AS `districtCode`,
`clients`.`zipCode`,
`clients`.`gender`,
`clients`.`startAge`,
`clients`.`endAge`,
`clients`.`mail`,
`clients`.`facebook`,
`clients`.`customerId`,
`clients`.`activityId`,
`surveys`.`name` AS `surveyName`,
`customers`.`companyName`,
`activities`.`name` AS `activityName`
FROM `freeAnswers`,
`clients`,
`surveys`,
`customers`,
`activities` AS `activities`
WHERE (freeAnswers.surveyId = surveys.id)
AND (surveys.customerId = customers.id)
AND (activities.id = surveys.activityId)
AND (clients.id = freeAnswers.clientId)
AND (customers.id = 1)
ORDER BY `activityName` ASC
LIMIT 10
So that will work but eventually you will want to rewrite it using JOIN instead of specifying most of the WHERE clauses.
When dealing with subqueries and Zend_Db_Select, I find it easy to write each subquery as their own queries before writing the final query, and just insert the subqueries where they need to go and Zend_Db handles the rest.
Hope that helps.