How can I convert this Firebase database to SQL database? - mysql

I am using Firebase for my project. Firebase database looks like that:
{
myObjects:{
1:{
index: '1',
body: 'foo1'
},
2:{
index: '1',
body: 'foo2'
},
3:{
index: '2',
body: 'foo3'
},
},
objectIndex: 1
}
As above, I have myObjects object and objectIndex variable. I was retrieving myObjects which index is same as objectIndex variable. objectIndex variable increments every 3 days and when it reaches 50 it turns into 0. So it is dynamic and I couldn't store it on the table.
Now I want to convert my Firebase database to MySQL.
MySQL will look like this:
|----|------|-------|
| id | body | index |
|----|------|-------|
| 1 | foo1 | 1 |
|----|------|-------|
| 2 | foo2 | 1 |
|----|------|-------|
| 3 | foo3 | 2 |
|----|------|-------|
Where I can store objectIndex variable?
I can update my table structure according to your suggestions.
Thanks in advance.

You can have a 1-row and 1-column "objectIndex" table where the value can be updated by using an SQL Cron-Job.
You can then build a query with a cartesian product that returns your data as follows:
|----|------|-------|-------------|
| id | body | index | objectIndex |
|----|------|-------|-------------|
| 1 | foo1 | 1 | 25 |
|----|------|-------|-------------|
| 2 | foo2 | 1 | 25 |
|----|------|-------|-------------|
| 3 | foo3 | 2 | 25 |
|----|------|-------|-------------|
It is redundant but gets the job done. The code to retrieve these values can be written as follows:
SELECT id, body, index, objectIndex
FROM objectTable, objectIndexTable

Related

MySQL - Search JSON data column

I have a MySQL database column that contains JSON array encoded strings. I would like to search the JSON array where the "Elapsed" value is greater than a particular number and return the corresponding TaskID value of the object the value was found. I have been attempting to use combinations of the JSON_SEARCH, JSON_CONTAINS, and JSON_EXTRACT functions but I am not getting the desired results.
[
{
"TaskID": "TAS00000012344",
"Elapsed": "25"
},
{
"TaskID": "TAS00000012345",
"Elapsed": "30"
},
{
"TaskID": "TAS00000012346",
"Elapsed": "35"
},
{
"TaskID": "TAS00000012347",
"Elapsed": "40"
}
]
Referencing the JSON above, if I search for "Elapsed" > "30" then 2 records would return
'TAS00000012346'
'TAS00000012347'
I am using MySQL version 5.7.11 and new to querying json data. Any help would be appreciated. thanks
With MySQL pre-8.0, there is no easy way to turn a JSON array to a recordset (ie, function JSON_TABLE() is not yet available).
So, one way or another, we need to manually iterate through the array to extract the relevant pieces of data (using JSON_EXTRACT()). Here is a solution that uses an inline query to generate a list of numbers ; another classic approchach is to use a number tables.
Assuming a table called mytable with a column called js holding the JSON content:
SELECT
JSON_EXTRACT(js, CONCAT('$[', n.idx, '].TaskID')) TaskID,
JSON_EXTRACT(js, CONCAT('$[', n.idx, '].Elapsed')) Elapsed
FROM mytable t
CROSS JOIN (
SELECT 0 idx
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
) n
WHERE JSON_EXTRACT(js, CONCAT('$[', n.idx, '].Elapsed')) * 1.0 > 30
NB: in the WHERE clause, the * 1.0 operation is there to force the conversion to a number.
Demo on DB Fiddle with your sample data:
| TaskID | Elapsed |
| -------------- | ------- |
| TAS00000012346 | 35 |
| TAS00000012347 | 40 |
Yes , you can definitely to it using JSON_EXTRACT() function in mysql.
lets take a table that contains JSON (table client_services here) :
+-----+-----------+--------------------------------------+
| id | client_id | service_values |
+-----+-----------+------------+-------------------------+
| 100 | 1000 | { "quota": 1,"data_transfer":160000} |
| 101 | 1000 | { "quota": 2,"data_transfer":800000} |
| 102 | 1000 | { "quota": 3,"data_transfer":70000} |
| 103 | 1001 | { "quota": 1,"data_transfer":97000} |
| 104 | 1001 | { "quota": 2,"data_transfer":1760} |
| 105 | 1002 | { "quota": 2,"data_transfer":1060} |
+-----+-----------+--------------------------------------+
And now lets say we want client_id for all who have quota>1 , then use this query :
SELECT
id,client_id,
JSON_EXTRACT(service_values, '$.quota') AS quota
FROM client_services
WHERE JSON_EXTRACT(service_values, '$.quota') > 1;
And hence it will result into :
+-----+-----------+-------+
| id | client_id | quota |
+-----+-----------+--------
| 101 | 1000 | 2 |
| 102 | 1000 | 3 |
| 104 | 1001 | 2 |
| 105 | 1002 | 2 |
+-----+-----------+-------+
hope this helps!

One to Many Count with one query?

I haven't touched the backend in a while.. so forgive me if this is super simple. I'm working with Lumen v.5.6.1.
| table.sets | | table.indexed_items |
|----------------| |---------------------------------|
| ID | SET | | ID | setId | itemId | have |
|----|-----------| |----|-------|--------|-----------|
| 1 | set name 1| | 1 | 3 | 1 | 2 |
| 2 | set name 2| | 2 | 3 | 2 | 1 |
| 3 | set name 3| | 3 | 3 | 3 | 4 |
| 4 | 2 | 4 | 1 |
| 5 | 2 | 5 | 3 |
| 6 | 2 | 6 | 1 |
How would I return in one query, groupedBy/distinct by setId (with set name as a left join?) to have a return like this:
[
setId: 2,
name: 'set name 2',
haveTotal: 5,
],
[
setId: 3,
name: 'set name 3',
haveTotal: 7,
]
Here is a raw MySQL query which should work. To convert this to Laravel should not be too much work, though you might need to use DB::raw once or twice.
SELECT
s.ID AS setId,
s.`SET` AS name,
COALESCE(SUM(ii.have), 0) AS haveTotal
FROM sets s
LEFT JOIN indexed_items ii
ON s.ID = ii.setId
GROUP BY
s.ID;
Demo
If you don't want to return sets having no entries in the indexed_items table, then you may remove the call to COALESCE, and you may also use an inner join instead of a left join.
Note that using SET to name your tables and columns is not a good idea because it is a MySQL keyword.
If you are using or want to use eloquent, you can do something like:
$sets = App\Sets::withCount('indexed_items')->get();
This will return a collection with a column name indexed_items_count
Obviously you will need to change depending on your model names.
Here are the docs
I always use in my project for count relation ship record.
$sets->indexed_items->count();

Get one row in table1 and Two or more rows in table2 in one array

Im newbie here. Suppose 2 tables in database:
Table 1: tournaments
+------------+----------+---------+----------+
| id | format | Size | host |
+------------+----------+---------+----------+
| 7 | Single | 9 | Daniel |
| 8 | Single | 4 | Oscar |
+------------+----------+---------+----------+
Table 2: matchs
+------------+----------+-------------+----------+----------+
| id | player | position | score | winner |
+------------+----------+-------------+----------+----------+
| 7 | Arturo | 0 | 3 | 1 |
| 7 | Pablo | 1 | 2 | 0 |
| 8 | Ale | 0 | 1 | 0 |
| 8 | Maria | 1 | 5 | 1 |
+------------+----------+-------------+----------+----------+
Now i want to get the host, size, winner, player, Score where ID is 7 and 8. Do you know how iget the following structure?:
[ Host:Daniel, size: 9, [ winner:1, player: Arturo, Score: 3], [winner:0, player: Pablo, Score: 2]], [host:Óscar, size:4,[winner:0, player: Ale, Score:0],....
Thanks in advance :)
Use JOIN Syntax to join the tables by id field:
SELECT
host, size, winner, player, score
FROM
tournaments INNER JOIN matchs USING (id);
If you want to select rows that contains specific idonly, then use WHERE clause. In your case append following to the query before semicolon:
WHERE `id` IN (7, 8)
Note, the MySQL can not create complex objects. SELECT returns set of rows only. To convert returned data set to structure, use external tools of your server side platform: C, C++, C#, VB.NET, Python, PHP, etc.

Extract data from json inside mysql field

I've got a a table with rows, and one of the rows has a field with data like this
{"name":"Richard","lastname":null,"city":"Olavarria","cityId":null}
And i want to select all the distinct "city" values i've got. Only using mysql server.
Is it possible? I'm trying with something like this
SELECT id FROM table_name WHERE field_name REGEXP '"key_name":"([^"]*)key_word([^"]*)"';
But i can't make the regexp work
Thanks in advance
MySQL has got support for JSON in version 5.7.7
http://mysqlserverteam.com/json-labs-release-native-json-data-type-and-binary-format/
You will be able to use the jsn_extract function to efficiently parse your JSON string.
If you have an older version and you want to solve it purely in mysql then I am afraid you have to treat it as a string and cut the value out of it (just normal string functions or use regular expressions)
This is not elegant but it will work
http://sqlfiddle.com/#!9/97cfd/14
SELECT
DISTINCT(substring(jsonfield, locate('"city":',jsonfield)+8,
locate('","', jsonfield, locate('"city":',jsonfield))-locate('"city":',jsonfield)-8)
)
FROM
ForgeRock
I have wrapped this into a stored function for those constrained to MySQL <5.7.7:
CREATE FUNCTION `json_extract_string`(
p_json text,
p_key text
) RETURNS varchar(40) CHARSET latin1
BEGIN
SET #pattern = CONCAT('"', p_key, '":"');
SET #start_i = LOCATE(#pattern, p_json) + CHAR_LENGTH(#pattern);
if #start_i = CHAR_LENGTH(#pattern) then
SET #end_i = 0;
else
SET #end_i = LOCATE('"', p_json, #start_i) - #start_i;
end if;
RETURN SUBSTR(p_json, #start_i, #end_i);
END
Note this only works with string values but is a bit more robust than #DmitryK's answer, in that it returns an empty string if the key is not found and the key can be anywhere in the JSON string.
Yes , you can definitely to it using JSON_EXTRACT() function in mysql.
lets take a table that contains JSON (table client_services here) :
+-----+-----------+--------------------------------------+
| id | client_id | service_values |
+-----+-----------+------------+-------------------------+
| 100 | 1000 | { "quota": 1,"data_transfer":160000} |
| 101 | 1000 | { "quota": 2,"data_transfer":800000} |
| 102 | 1000 | { "quota": 3,"data_transfer":70000} |
| 103 | 1001 | { "quota": 1,"data_transfer":97000} |
| 104 | 1001 | { "quota": 2,"data_transfer":1760} |
| 105 | 1002 | { "quota": 2,"data_transfer":1060} |
+-----+-----------+--------------------------------------+
To Select each JSON fields , run this query :
SELECT
id, client_id,
json_extract(service_values, '$.quota') AS quota,
json_extract(service_values, '$.data_transfer') AS data_transfer
FROM client_services;
So the output will be :
+-----+-----------+----------------------+
| id | client_id | quota | data_transfer|
+-----+-----------+----------------------+
| 100 | 1000 | 1 | 160000 |
| 101 | 1000 | 2 | 800000 |
| 102 | 1000 | 3 | 70000 |
| 103 | 1001 | 1 | 97000 |
| 104 | 1001 | 2 | 1760 |
| 105 | 1002 | 2 | 1060 |
+-----+-----------+----------------------+
NOW, if you want lets say DISTINCT quota , then run this query :
SELECT
distinct( JSON_EXTRACT(service_values, '$.quota')) AS quota
FROM client_services;
So this will result into your desired output :
+-------+
| quota |
+-------+
| 1 |
| 2 |
| 3 |
+-------+
hope this helps!
See MariaDB's Dynamic Columns.
Also, search this forum for [mysql] [json]; the topic has been discussed often.
This may be a little late, but the accepted answer didn't work for me. I used SUBSTRING_INDEX to achieve the desired result.
SELECT
ID, SUBSTRING_INDEX(SUBSTRING_INDEX(JSON, '"mykey" : "', -1), '",', 1) MYKEY
FROM MY_TABLE;
Hope this helps.

Hibernate Query in entire table with unique lines selects

I'm wondering how to filter Hibernate results.
For example, I have this example table:
--------------------------------------------
| ID | STRING | DATE |
--------------------------------------------
| 1 | "ABC" | 2014-11-07 21:45:00 |
--------------------------------------------
| 2 | "ABC" | 2014-11-07 22:45:00 |
--------------------------------------------
| 3 | "DCE" | 2014-11-07 22:48:00 |
--------------------------------------------
| 4 | "ABC" | 2014-11-07 23:48:00 |
--------------------------------------------
The result that I need is:
--------------------------------------------
| ID | STRING | DATE |
--------------------------------------------
| 3 | "DCE" | 2014-11-07 22:48:00 |
--------------------------------------------
| 4 | "ABC" | 2014-11-07 23:48:00 |
--------------------------------------------
All lines of table, BUT, when I have the same content in column STRING, the column with the most recent DATE is the one in result set.
In hibernate I know
- select ALL lines;
- select the repeated lines and keep only the most recent.
But I don't know how to combine the two situations together, and I can't find it referenced anywhere.
I have a fixed length in STRING, and I use a fake primary key in my code to identify the register, but the value is inserted by user, and I have no previous knowledge of the content in the column.
You can do this using a not exists clause:
select e.*
from example e
where not exists (select 1 from example e2 where e2.string = e.string and e2.date > e.date);
That is, select all rows where there is no other row with the same string and a larger date.