table provider
table provider_properties
here I wanted the result something like
{
"provider_uuid": "b897f790-ee90-4869-9345-690380b1a0c9",
"name": "Provider 1",
"password": "112233",
"username": "provider_1",
"properties": {
"address_1": "Dubai",
"address_2": "NY"
}
}
here i tried something like
SELECT provider.*, json_object(provider_properties.key_name, provider_properties.key_value) as properties FROM provider JOIN provider_properties on provider.provider_id = provider_properties.provider_uuid;
but the problem is i am getting 2 rows
Since your expected results need specific formatting in json. You want to refer to JSON Formatted output. This is for shell though.
You might also want to try this...
This would give you a tabular results but in one row.
SELECT
provider.*,
p_props.properties
FROM provider
JOIN (
provider_uuid,
SELECT JSON_OBJECTAGG(
provider_properties.key_name,
provider_properties.key_value
) as properties
FROM provider_properties
GROUP BY provider_uuid
) p_props ON provider.provider_id = p_props.provider_uuid;
CONCAT() and REPLACE() here are used for sorting the order of columns.
I would say the use of REPLACE() here is quite risky, please test it out and see how it goes.
db<>fiddle
SELECT
p.*,
CONCAT(
'{"', 'provider_uuid": "', pp.provider_uuid, '"',
REPLACE(JSON_OBJECT('name', p.name, 'password', p.password,
'username', p.username, 'properties', pp.name_value), '{"name', ', "name')
) AS your_json
FROM provider p
JOIN (
SELECT provider_uuid, JSON_OBJECTAGG(key_name, key_value) as name_value
FROM provider_properties
GROUP BY provider_uuid
) pp ON p.provider_id = pp.provider_uuid;
Related
I have a table that has some columns.
One of these columns stores data in JSON format.
I select a row from this table with FOR JSON AUTO.
My problem is that SQL Server puts quotations around the value of JSON properties but I don't want this; because I want to use the values of inner JSON with JSON_VALUE(). What can I do?
Code:
SELECT TOP 1 *
FROM users;
Result:
name lastName age favorites
John Duo 20 {"city": "paris", "color": "blue", "sport": "football"}
Code:
SELECT TOP 1 *
FROM users
FOR JSON AUTO, WITHOUT_ARRAY_WRAPPER;
Result:
{"name":"John","lastName":"Duo","age":20,"favorites":"{\"city\": \"paris\", \"color\": \"blue\", \"sport\": \"football\"}"}
Code:
SELECT JSON_VALUE(#user_json,'$.favorites.color')
Result:
NULL
I can use this trick to get values from inner JSON, but it's not clean.
Code:
SELECT JSON_VALUE(JSON_VALUE(#user_json,'$.favorites'), '$.color')
Result:
blue
How can I do this in a clean way?
Some code for testing in SQL Server:
DROP TABLE IF EXISTS #test_tbl;
DECLARE #user_json AS NVARCHAR(MAX);
SELECT 'John' AS Name, 'Duo' AS LastName, 20 AS Age, '{"city": "paris", "color": "blue", "sport": "football"}' AS favorites
INTO #test_tbl;
SET #user_json =
(
SELECT *
FROM #test_tbl
FOR JSON AUTO, WITHOUT_ARRAY_WRAPPER
)
SELECT JSON_VALUE(#user_json,'$.favorites.color');
SELECT JSON_VALUE(JSON_VALUE(#user_json,'$.favorites'),'$.color');
You need to nest the favorites JSON using json_query(), e.g.:
SET #user_json =
(
SELECT Name, LastName, Age, json_query(favorites) as favorites
FROM #test_tbl
FOR JSON AUTO, WITHOUT_ARRAY_WRAPPER
)
SELECT JSON_VALUE(#user_json,'$.favorites.color');
# (No column name)
# ----------------
# blue
I am a newbie to Couchbase DB server and I am trying to achieve with one query what I have done with three queries as this is not so efficient.
I have three different documents types (x,y,z) in the same bucket; all having a similar key: 'district' like so:
document x:
{
"type": "x",
"district": "Some district"
}
document y:
{
"type": "y",
"district": "Some district"
}
document z:
{
"type": "z",
"district": "Some district"
}
I have currently implemented something like the following pseudo-code in PHP:
$totalDistrictInX = "SELECT COUNT(x) FROM bucket WHERE type = 'x' AND district = 'Maboro';
$totalDistrictInY = "SELECT COUNT(x) FROM bucket WHERE type = 'y' AND district = 'Maboro';
$totalDistrictInZ = "SELECT COUNT(x) FROM bucket WHERE type = 'z' AND district = 'Maboro';
$totalCountOfMaboro = $totalDistrictInX + $totalDistrictInY + $totalDistrictInZ;
I cannot use a JOIN query because the Couchbase server currently in use is below 5.50 which only supports joining documents between document key to document field and not between document fields.
Is there a way to achieve this with one just n1ql query? Any help will be much appreciated, please.
Use aggregate query without group by for total count, control what documents to count through predicate.
SELECT COUNT(1) AS cnt
FROM bucket
WHERE type IN ['x', 'y', 'z'] AND district = 'Maboro';
If you need count for each type use GROUP BY
SELECT type, COUNT(1) AS cnt
FROM bucket
WHERE type IN ['x', 'y', 'z'] AND district = 'Maboro'
GROUP BY type;
If you want total count and individual type, its counts as array
SELECT ARRAY_SUM(av[*].cnt) AS totalcnt, av AS details
LET av = (SELECT type, COUNT(1) AS cnt
FROM bucket
WHERE type IN ['x', 'y', 'z'] AND district = 'Maboro'
GROUP BY type);
Could a GROUP BY and COUNT combo be your solution?
SELECT COUNT(x) FROM bucket WHERE district = 'Maboro' GROUP BY type
Documentation
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.
In my situation, entreprise(company) can have several sites(filiales), I want to get all the filiales with format array.
In the json entreprise(company), there is no information of sites(filiales), In the json sites(filiales), it has entreprise(company) uid.
Json entreprise(company):
{
"type": "entreprise",
"dateUpdate": 1481716305279,
"owner": {
"type": "user",
"uid": "PNnqarPqSdaxmEJ4DoMv-A"
}
}
Json sites(filiales):
{
"type": "site",
"entreprise": {
"uid": "3c0CstzsTjqPdycL5yYzJQ",
"type": "entreprise"
},
"nom": "test"
}
The query I tried:
SELECT
META(entreprise).id as uid,
ARRAY s FOR s IN (SELECT d.* FROM default d WHERE d.type = "site" AND d.entreprise.uid = uid) END as sites,
entreprise.*
FROM default entreprise
WHERE entreprise.type = "entreprise";
Result: error
{
"code": 5010,
"msg": "Error evaluating projection. - cause: FROM in correlated subquery must have USE KEYS clause: FROM default."
}
Then i use alias:
SELECT
META(entreprise).id as uid,
ARRAY s FOR s IN (SELECT d.* FROM default d WHERE d.type = "site" AND d.entreprise.uid = META(entreprise).id) END as sites,
entreprise.*
FROM default entreprise
WHERE entreprise.type = "entreprise";
Result: sites array is empty.
First you have to create an index on your site documents :
CREATE INDEX site_ent_idx ON default(entreprise.uid) WHERE type="site";
Then change your query to use the new index :
SELECT
META(entreprise).id as uid,
ARRAY s FOR s IN (
SELECT site.*
FROM default as ent USE KEYS META(entreprise).id
JOIN default as site ON KEY site.entreprise.uid FOR ent
) END as sites,
entreprise.*
FROM default entreprise
WHERE entreprise.type = "entreprise"
This solution should meet your needs.
You need to perform an index join from sites to enterprises. See https://dzone.com/articles/join-faster-with-couchbase-index-joins
After that, use GROUP BY and ARRAY_AGG() to collect the sites into arrays.
When I try to execute this query I got trouble.
INSERT INTO af_pres (cod,pres,fecha,tipo,stad,oper,ref,monto)
VALUES
("",
(CASE
(SELECT p.pres FROM af_pres p WHERE
p.pres LIKE "%0100000100191000140100%" AND
p.fecha LIKE "%2014%" = ''
THEN pres ELSE
(pres = "2014"))END),
"2014-09-26","G","1","M","MOD-2014",70000);
You can not use SELECT in CASE as you are doing in your query. MySQL does not have this feature built in.
If you describe what you want to do, we can help you more.
Ok here is a solution, but I have not tried it :)
INSERT INTO af_pres (cod,pres,fecha,tipo,stad,oper,ref,monto)
VALUES
("",
(SELECT IF (COUNT(p.pres) > 0, pres, '2014')
FROM af_pres p
WHERE p.pres LIKE "%0100000100191000140100%"
AND p.fecha LIKE "%2014%" = ''),
"2014-09-26",
"G",
"1",
"M",
"MOD-2014",
70000);