I have a table,
t_offices
id name offices
2 london {"officeIds": [1, 33, 13, 1789]}
3 bangkok {"officeIds": [2, 3, 40, 19]}
I can get the array in the json body using
select JSON_EXTRACT(p.`offices`, '$.officeIds[*]') from t_offices p
It leads to
[1, 33, 13, 1789]
[2, 3, 40, 19]
But Now, How to search with a condition that it would have value 33.
i.e
2 London {"officeIds": [1, 33, 13, 1789]}
basically, get the row where a value is inside that json array.
You can try with this query:
SELECT * FROM t_offices WHERE JSON_CONTAINS(offices, '33', '$.officeIds');
OR
SELECT * FROM t_offices WHERE JSON_CONTAINS(offices->'$.officeIds', '33');
I have a psql table where one of the jsonb data is extracted over it.
{
"SrcRcs": [4, 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 158],
"reason": "",
"result": "Success",
"InitTech": 1
}
This column is named Data and is of type jsonb.
I am extracting the SrcRcs data from the jsonb:
select Data->'SrcRcs' from table_name;
Output:
[4, 0, 1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 158]
But which is in unsorted order as from the jsonb.
I want it in the sorted order like this:
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,158]
Can someone please help me out?
I have tried the psql sort() but wasn't able to achieve the desired result.
You need to unnest the array elements and then aggregate them back in a sorted way:
SELECT (select jsonb_agg(i::int order by i::int)
from jsonb_array_elements(data -> 'SrcRcs') as t(i))
from the_table
If you want, you can create a function for this to make the SQL queries easier.
I have a table named flup and some datas like:
pid, flup_time, degree, oc, flup_type
1, 2018-05-06, 1, 0, 2
1, 2018-08-01, 2, 0, 3
1, 2018-08-13, 2, 0, 1
1, 2018-08-25, 2, 1, 1
1, 2018-11-20, 2, 1, 2
1, 2019-01-09, 2, 1, 2
2, 2018-06-01, 1, 0, 2
2, 2018-08-27, 2, 0, 2
2, 2018-11-30, 2, 0, 2
...
First, find all datas group by pid, for this pid (here pid=1), order by flup_time asc. Give a period of time (like from 2018-01-01 to 2019-07-01), for every row, make rules:
rule1. if degree = 1, then next flup_time must in 90 days.
rule2. if degree = 2 and oc != 1, then next flup_time must in 15 days.
rule3. if degree = 2 and oc = 1, then next flup_time must in 90 days.
I want to create a view (flup_view), has all the columns of flup, and more column named pass_check. If the row met the rule1,2,3, pass_check = 1, otherwise pass_check = 2. Like:
pid, flup_time, degree, oc, flup_type, pass_check
1, 2018-05-06, 1, 0, 2, -1
1, 2018-08-01, 2, 0, 3, 1
1, 2018-08-13, 2, 0, 1, 1
1, 2018-08-25, 2, 1, 1, 1
1, 2018-11-20, 2, 1, 2, 1
1, 2019-01-09, 2, 1, 2, 1
2, 2018-06-01, 1, 0, 2, -1
2, 2018-08-27, 2, 0, 2, 1
2, 2018-11-30, 2, 0, 2, 2
How to do this by sql please?
There are a couple of pieces that you'll need for this to work. I'm not sure how strong your SQL background is, so I'll include the basics as well.
First, in order to create the rule, you'll need to use a CASE WHEN:
https://www.w3schools.com/sql/func_mysql_case.asp
Next, you need to get the following row for each ID, you need to use the LEAD function. Here's a general overview:
https://dev.mysql.com/doc/refman/8.0/en/window-function-descriptions.html
and a tutorial for LAG, which is the same as LEAD, but it checks the row above rather than the row below:
http://www.mysqltutorial.org/mysql-window-functions/mysql-lag-function/
(LEAD didn't exist in early version of MySQL, so your version might not have this)
Finally, you want to compare dates using the DATE_ADD function:
https://www.w3schools.com/sql/func_mysql_date_add.asp
It will be a little complicated, but these three things should be enough to let you build the query you need.
I have a matrix like this
A =
[0, 0, 0, 1, 3, 7, NA;
0, 0, 3, 5, 7, NA, NA;
0, 2, 3, 4, 5, 6, NA;
0, 0, 4, 5, 6, 7, NA;]
I want to extract the minimum values in each row of the matrix A that is greater than 0 into a vector B:
B = [1;3;2;4]
Any suggestion?
Thank you very much.
A(A<=0)=NA;
B=min(A, [], 2)
As suggested by Matt I'll explain this a little bit. Because you don't want results <=0 I set them to NA. You already have some in your data and the "min" operation will ignore them.
In the second step we search the minimum in the rows (2. dimension).
I have a table which stores yes/no values for each hour of the day for a particular user/filter/type. Each day is its own row. So there will always be 7 rows for any given user/filter/type combination.
What I am trying to accomplish is one result for each user/filter/type combination that contains all hours of each day of the week. I think the approach I need here is self joining with aliases and groups, but everything I have tried fails. I have setup a basic fiddle at fiddle
I also have the ability to change the db schema for this as well if there is an easier and/or preferred method to handle this on the db side (my gut says there is). Perhaps a table for each day of the week linked by filter_id?
INSERT INTO filters
(`filter_id`, `user_id`, `filter`, `type`, `day`, `12a`, `1a`... and so on for each hour)
VALUES
(1, 1, 'filter1', 1, 1, 1, 1),
(2, 1, 'filter1', 1, 2, 1, 1),
(3, 1, 'filter1', 1, 3, 1, 1),
(4, 1, 'filter1', 1, 4, 1, 1),
(5, 1, 'filter1', 1, 5, 1, 1),
(6, 1, 'filter1', 1, 6, 1, 1),
(7, 1, 'filter1', 1, 7, 1, 1),
(8, 1, 'filter2', 1, 1, 0, 0),
(9, 1, 'filter2', 1, 2, 0, 0),
(10, 1, 'filter2', 1, 3, 0, 0),
(11, 1, 'filter2', 1, 4, 0, 0),
(12, 1, 'filter2', 1, 5, 0, 0),
(13, 1, 'filter2', 1, 6, 0, 0),
(14, 1, 'filter2', 1, 7, 0, 0),
(15, 1, 'filter3', 1, 1, 0, 0),
(16, 1, 'filter3', 1, 2, 0, 0),
(17, 1, 'filter3', 1, 3, 0, 0),
(18, 1, 'filter3', 1, 4, 0, 0),
(19, 1, 'filter3', 1, 5, 0, 0),
(20, 1, 'filter3', 1, 6, 0, 0),
(21, 1, 'filter3', 1, 7, 0, 0)
;
EDIT :
I made some progress on this and it is showing all day hours for the filter in one result...however... I it does not work when a user has more than one filter. I can't seem to get the grouping correct and/or something else so results only show unique user/type/filter combinations... at the moment it only shows one filter result for each user.
This is only joining monday, tuesday, wednesday as well... there must be an easier way to do this. Like I said I am totally open up to changing the schema of the db for this as well, but not sure what the best approach would be other than this. I certainly cannot list all the hours for the entire week in one table (that would be 168 columns for hours plus an additional for for 172 in each row).
$stmt = $db->prepare("
SELECT users.user_id, users.username, c.computer_name, filters.user_id, filters.filter, filters.type,
monday.12a as m12a,
monday.1a as m1a,
monday.2a as m2a,
monday.3a as m3a,
monday.4a as m4a,
monday.5a as m5a,
monday.6a as m6a,
monday.7a as m7a,
monday.8a as m8a,
monday.9a as m9a,
monday.10a as m10a,
monday.11a as m11a,
monday.12p as m12p,
monday.1p as m1p,
monday.2p as m2p,
monday.3p as m3p,
monday.4p as m4p,
monday.5p as m5p,
monday.6p as m6p,
monday.7p as m8p,
monday.9p as m9p,
monday.10p as m10p,
monday.11p as m11p,
tuesday.12a as t12a,
tuesday.1a as t1a,
tuesday.2a as t2a,
tuesday.3a as t3a,
tuesday.4a as t4a,
tuesday.5a as t5a,
tuesday.6a as t6a,
tuesday.7a as t7a,
tuesday.8a as t8a,
tuesday.9a as t9a,
tuesday.10a as t10a,
tuesday.11a as t11a,
tuesday.12p as t12p,
tuesday.1p as t1p,
tuesday.2p as t2p,
tuesday.3p as t3p,
tuesday.4p as t4p,
tuesday.5p as t5p,
tuesday.6p as t6p,
tuesday.7p as t8p,
tuesday.9p as t9p,
tuesday.10p as t10p,
tuesday.11p as t11p,
wednesday.12a as w12a,
wednesday.1a as w1a,
wednesday.2a as w2a,
wednesday.3a as w3a,
wednesday.4a as w4a,
wednesday.5a as w5a,
wednesday.6a as w6a,
wednesday.7a as w7a,
wednesday.8a as w8a,
wednesday.9a as w9a,
wednesday.10a as w10a,
wednesday.11a as w11a,
wednesday.12p as w12p,
wednesday.1p as w1p,
wednesday.2p as w2p,
wednesday.3p as w3p,
wednesday.4p as w4p,
wednesday.5p as w5p,
wednesday.6p as w6p,
wednesday.7p as w8p,
wednesday.9p as w9p,
wednesday.10p as w10p,
wednesday.11p as w11p
FROM
( SELECT account_id, computer_id, computer_name
FROM computers
WHERE account_id = 1
ORDER BY computer_id ASC LIMIT 0, 5
) as c
LEFT JOIN users
on users.computer_id = c.computer_id
LEFT JOIN filters
on filters.user_id = users.user_id
LEFT JOIN filters as monday
on monday.user_id = filters.user_id and monday.filter = filters.filter and monday.day = 1
LEFT JOIN filters as tuesday
on tuesday.user_id = filters.user_id and tuesday.filter = filters.filter and tuesday.day = 2
LEFT JOIN filters as wednesday
on wednesday.user_id = filters.user_id and wednesday.filter = filters.filter and wednesday.day = 3
WHERE filters.type = 1
GROUP BY users.user_id
");
The INNER JOIN keyword selects all rows from both tables as long as there is a match between the columns in both tables.
SELECT column_name(s)
FROM table1
INNER JOIN table2
ON table1.column_name=table2.column_name;
Here is the official mysql page. http://dev.mysql.com/doc/refman/5.0/en/join.html