How to index nested array - json

How to index (N1QL query in Couchbase) above document to speed up searching by SerialNumber field in nested array (doc => groups => items => item.SerialNumber)?
Sample:
{
"Id": "0012ed6e-41af-4e45-b53f-bac3b2eb0b82",
"Machine": "Machine2",
"Groups": [
{
"Id": "0fed9b14-fa38-e511-893a-001125665867",
"Name": "Name",
"Items": [
{
"Id": "64e69b14-fa38-e511-893a-001125665867",
"SerialNumber": "1504H365",
"Position": 73
},
{
"Id": "7be69b14-fa38-e511-893a-001125665867",
"SerialNumber": "1504H364",
"Position": 72
}
]
},
{
"Id": "0fed9b14-fa38-e511-893a-001125665867",
"Name": "Name",
"Items": [
{
"Id": "64e69b14-fa38-e511-893a-001125665867",
"SerialNumber": "1504H365",
"Position": 73
},
{
"Id": "7be69b14-fa38-e511-893a-001125665867",
"SerialNumber": "1504H364",
"Position": 72
}
]
}
]
}
my query:
CREATE INDEX idx_serial ON `aplikomp-bucket`
(ALL ARRAY(ALL ARRAY i.SerialNumber FOR i IN g.Items END ) FOR g In Groups END);

CREATE INDEX idx_serial ON `aplikomp-bucket` (DISTINCT ARRAY(DISTINCT ARRAY i.SerialNumber FOR i IN g.Items END ) FOR g In Groups END);
SELECT META().id FROM `aplikomp-bucket` AS a
WHERE ANY g IN a.Groups SATISFIES (ANY i IN g.Items SATISFIES i.SerialNumber > 123 END) END;

Related

Select from mysql array of objects with integer number and value null or source to file without duplicates

Let's say I have a table with rows like number, image. But image is not mandatory, It can be null and when I'm selecting I want to prioritize the row with image over the one with null so i could get clean array with only one row per number.
SELECT DISTINCT number, image FROM table ORDER BY number ASC
What's now with SELECT DISTINCT:
[
{
"number": 1,
"image": null
},
{
"number": 1,
"image": "https://example.com/image1.png"
},
{
"number": 2,
"image": null
},
{
"number": 2,
"image": "https://example.com/image2.png"
},
{
"number": 3,
"image": "https://example.com/image3.png"
},
{
"number": 3,
"image": null
},
{
"number": 4,
"image": null
}
]
What I want to get:
[
{
"number": 1,
"image": "https://example.com/image1.png"
},
{
"number": 2,
"image": "https://example.com/image2.png"
},
{
"number": 3,
"image": "https://example.com/image3.png"
},
{
"number": 4,
"image": null
}
]
Try this:
SELECT number, image FROM table ORDER BY ISNULL(LEFT(image,0));

How to join tables and get the json output using jooq

dslContext.select(
jsonObject(
key("id").value(CATEGORY.ID),
key("courses").value(
jsonArrayAgg(
jsonObject(
Arrays.stream(COURSE.fields())
.map(i -> key(CamelcaseConverter.snakeToCamel(i.getName())).value(
i))
.collect(
Collectors.toList())
)
)
)
)
).from(CATEGORY)
.leftJoin(COURSE_CATEGORY).on(CATEGORY.ID.eq(COURSE_CATEGORY.CATEGORY_ID))
.leftJoin(COURSE).on(COURSE.ID.eq(COURSE_CATEGORY.COURSE_ID)).fetchInto(JSONObject.class)
Output I got:
[
{
"courses": [
{
"id": 19
},
{
"id": null
}
],
"name": "Exam1",
"id": 1,
}
]
The required output is
[
{
"courses": [
{
"id": 19
}
],
"name": "Exam1",
"id": 1
},
{
"courses":[],
"name": "Exam2",
"id": 2
}
]
The query which need to be executed is
"select * from category left outer join course_category on category.id = course_category.category_id left outer join course on course_category.course_id = course.id"
how do I implement it?
You forgot to group by:
.groupBy(CATEGORY.ID, CATEGORY.NAME)
If you have a primary (or unique) key on CATEGORY.ID, then in MySQL, it will be sufficient to group by that
.groupBy(CATEGORY.ID)

couchbase N1QL group-by in sub-document

given the below data model:
{
"events": [
{
"customerId": "a",
"type": "credit" ,
"value": 10
},
{
"customerId": "a",
"type": "credit" ,
"value": 10
},
{
"customerId": "b",
"type": "credit" ,
"value": 5
},
{
"customerId": "b",
"type": "credit" ,
"value": 5
}
]
}
how can i query the sum of credits by customerId ? i.e:
{
{
"customerId": "a",
"total": "20
},
{
"customerId": "b",
"total": "10
}
}
Use SUBQUERY expression per document aggregation
SELECT d.*,
(SELECT e.customerId, SUM(e.`value`) AS total
FROM d.events AS e
WHERE ......
GROUP BY e.customerId) AS events
FROM default AS d
WHERE ...........;
For Whole Query
SELECT e.customerId, SUM(e.`value`) AS total
FROM default AS d
UNNEST d.events AS e
WHERE ......
GROUP BY e.customerId;

Select Json formatted like a report to a table using T-SQL

I have JSON stored in a SQL Server database table in the below format. I have been able to fudge a way to get the values I need but feel like there must be a better way to do it using T-SQL. The JSON is output from a report in the below format where the column names in "columns" correspond to the "rows"-"data" array values.
So column "Fiscal Month" corresponds to data value "11", "Fiscal Year" to "2019", etc.
{
"report": "Property ETL",
"id": 2648,
"columns": [
{
"name": "Fiscal Month",
"dataType": "int"
},
{
"name": "Fiscal Year",
"dataType": "int"
},
{
"name": "Portfolio",
"dataType": "varchar(50)"
},
{
"name": "Rent",
"dataType": "int"
}
],
"rows": [
{
"rowName": "1",
"type": "Detail",
"data": [
11,
2019,
"West Group",
10
]
},
{
"rowName": "2",
"type": "Detail",
"data": [
11,
2019,
"East Group",
10
]
},
{
"rowName": "3",
"type": "Detail",
"data": [
11,
2019,
"East Group",
10
]
},
{
"rowName": "Totals: ",
"type": "Total",
"data": [
null,
null,
null,
30
]
}
]
}
In order to get at the data in the 'data' array I currently have a 2 step process in T-SQL where I create a temp table, and insert the row key/values from '$.Rows' there. Then I can then select the individual columns for each row
CREATE TABLE #TempData
(
Id INT,
JsonData VARCHAR(MAX)
)
DECLARE #json VARCHAR(MAX);
DECLARE #LineageKey INT;
SET #json = (SELECT JsonString FROM Stage.Report);
SET #LineageKey = (SELECT LineageKey FROM Stage.Report);
INSERT INTO #TempData(Id, JsonData)
(SELECT [key], value FROM OPENJSON(#json, '$.rows'))
MERGE [dbo].[DestinationTable] TARGET
USING
(
SELECT
JSON_VALUE(JsonData, '$.data[0]') AS FiscalMonth,
JSON_VALUE(JsonData, '$.data[1]') AS FiscalYear,
JSON_VALUE(JsonData, '$.data[2]') AS Portfolio,
JSON_VALUE(JsonData, '$.data[3]') AS Rent
FROM #TempData
WHERE JSON_VALUE(JsonData, '$.data[0]') is not null
) AS SOURCE
...
etc., etc.
This works, but I want to know if there is a way to directly select the data values without the intermediate step of putting it into the temp table. The documentation and examples I've read seem to all require that the data have a name associated with it in order to access it. When I try and access the data directly at a position by index I just get Null.
I hope I understand your question correctly. If you know the columns names you need one OPENJSON() call with explicit schema, but if you want to read the JSON structure from $.columns, you need a dynamic statement.
JSON:
DECLARE #json nvarchar(max) = N'{
"report": "Property ETL",
"id": 2648,
"columns": [
{
"name": "Fiscal Month",
"dataType": "int"
},
{
"name": "Fiscal Year",
"dataType": "int"
},
{
"name": "Portfolio",
"dataType": "varchar(50)"
},
{
"name": "Rent",
"dataType": "int"
}
],
"rows": [
{
"rowName": "1",
"type": "Detail",
"data": [
11,
2019,
"West Group",
10
]
},
{
"rowName": "2",
"type": "Detail",
"data": [
11,
2019,
"East Group",
10
]
},
{
"rowName": "3",
"type": "Detail",
"data": [
11,
2019,
"East Group",
10
]
},
{
"rowName": "Totals: ",
"type": "Total",
"data": [
null,
null,
null,
30
]
}
]
}'
Statement for fixed structure:
SELECT *
FROM OPENJSON(#json, '$.rows') WITH (
[Fiscal Month] int '$.data[0]',
[Fiscal Year] int '$.data[1]',
[Portfolio] varchar(50) '$.data[2]',
[Rent] int '$.data[3]'
)
Dynamic statement:
DECLARE #stm nvarchar(max) = N''
SELECT #stm = CONCAT(
#stm,
N',',
QUOTENAME(j2.name),
N' ',
j2.dataType,
N' ''$.data[',
j1.[key],
N']'''
)
FROM OPENJSON(#json, '$.columns') j1
CROSS APPLY OPENJSON(j1.value) WITH (
name varchar(50) '$.name',
dataType varchar(50) '$.dataType'
) j2
SELECT #stm = CONCAT(
N'SELECT * FROM OPENJSON(#json, ''$.rows'') WITH (',
STUFF(#stm, 1, 1, N''),
N')'
)
PRINT #stm
EXEC sp_executesql #stm, N'#json nvarchar(max)', #json
Result:
--------------------------------------------
Fiscal Month Fiscal Year Portfolio Rent
--------------------------------------------
11 2019 West Group 10
11 2019 East Group 10
11 2019 East Group 10
30
Yes, it is possible without temporary table:
DECLARE #json NVARCHAR(MAX) =
N'
{
"report": "Property ETL",
"id": 2648,
"columns": [
{
"name": "Fiscal Month",
"dataType": "int"
},
{
"name": "Fiscal Year",
"dataType": "int"
},
{
"name": "Portfolio",
"dataType": "varchar(50)"
},
{
"name": "Rent",
"dataType": "int"
}
],
"rows": [
{
"rowName": "1",
"type": "Detail",
"data": [
11,
2019,
"West Group",
10
]
},
{
"rowName": "2",
"type": "Detail",
"data": [
11,
2019,
"East Group",
10
]
},
{
"rowName": "3",
"type": "Detail",
"data": [
11,
2019,
"East Group",
10
]
},
{
"rowName": "Totals: ",
"type": "Total",
"data": [
null,
null,
null,
30
]
}
]
}
}';
And query:
SELECT s.value,
rowName = JSON_VALUE(s.value, '$.rowName'),
[type] = JSON_VALUE(s.value, '$.type'),
s2.[key],
s2.value
FROM OPENJSON(JSON_QUERY(#json, '$.rows')) s
CROSS APPLY OPENJSON(JSON_QUERY(s.value, '$.data')) s2;
db<>fiddle demo
Or as a single row per detail:
SELECT s.value,
rowName = JSON_VALUE(s.value, '$.rowName'),
[type] = JSON_VALUE(s.value, '$.type'),
JSON_VALUE(s.value, '$.data[0]') AS FiscalMonth,
JSON_VALUE(s.value, '$.data[1]') AS FiscalYear,
JSON_VALUE(s.value, '$.data[2]') AS Portfolio,
JSON_VALUE(s.value, '$.data[3]') AS Rent
FROM OPENJSON(JSON_QUERY(#json, '$.rows')) s;
db<>fiddle demo 2

mysql: json based query

Code:
CREATE TABLE t1(jdoc JSON);
INSERT INTO t1 VALUES('{
"data":
[
{
"type": "required",
"member": {
"id" : "1001",
"response": "none"
}
},
{
"type": "notrequired",
"member": {
"id" : "1009",
"response": "accepted"
}
}
]
}');
INSERT INTO t1 VALUES('{
"data":
[
{
"type": "maybe",
"member": {
"id" : "1002",
"response": "none"
}
},
{
"type": "maybe",
"member": {
"id" : "1003",
"response": "accepted"
}
}
]
}');
I have two questions.
First is to get rows which has 1002 as memeber.id. I tried two queries for this and both are not working.
SELECT * FROM t1 where JSON_CONTAINS(jdoc, JSON_QUOTE('1002'), '$.data[*].memeber.id');
SELECT * FROM t1 where JSON_EXTRACT(jdoc, '$.data[*].memeber.id') = '1002';
Second is to get the rows which has type = 'required' and corresponding member.id = "1001"
Help me with the queries.