How to make a rule by sql please? - mysql

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.

Related

Musician wants to know the programming term for this function

My apologies that I don't use always use programming terms in my description - I am a musician who has only dabbled in programming.
Suppose I have a list of numbers named a:
a = (0, 2, 4, 5, 7, 9, 11, 12)
and from the list a the following list of numbers is randomly generated to create list b:
b = (4, 7, 5, 7, 9, 11, 9)
Then I want to have "transpositions" (this is a musical term) of list b, such as those shown in lists c, d, and e:
c = (5, 9, 7, 9, 11, 12, 11) or d = (2, 5, 4, 5, 7, 9, 11, 9) or e = (0, 4, 2, 4, 5, 7, 9, 7)
What do you call this "transposition" of this list of numbers in programming terms, and what bit of programming code would accomplish this task? My best guess is that it has to do with the indexing of the numbers in list a, and when list b is created the indexes of list b are put in a list such as list f:
f = (2, 4, 3, 4, 5, 6, 5)
so that the "transposition" is accomplished by adding or subtracting a specific number from each number in list f. For example, the numbers in list c are generated by adding 1 to each of the numbers in list f:
(3, 5, 4, 5, 6, 7, 6)
the numbers in list d are generated by subtracting 1 to each of the numbers in list f:
(1, 3, 2, 3, 4, 5, 4)
and the numbers in list e are generated by subtracting 2 to each of the index numbers taken from list f:
(0, 2, 1, 2, 3, 4, 3)
Or if anyone has a better idea, please let me know.
An operation like "add 1 to every member of this list, to generate a new list" is usually called a map.

How to move column data to next row until end starting on specified key

I have a table named network_table with this data example:
NetworkTableID, MainID, UserID
1, 1, 1
2, 1, 2
3, 1, 3
4, 1, 4
5, 2, 5
So I want to move all the columns data of UserID to the next row starting from NetworkTableID: 2 until the end of the table and there will be another inserted row because the rows moved. I'm expecting a result like this:
NetworkTableID, MainID, UserID
1, 1, 1
2, 1, 2
3, 1, 2
4, 1, 3
5, 2, 4
6, 2, 5
This query don't work for me. It gives me a "#1093 - You can't specify target table 'network_table' for update in FROM clause" error.
UPDATE network_table
SET UserID = (SELECT UserID FROM network_table as nt2
WHERE nt2.NetworkTableID=network_table.NetworkTableID-1)
WHERE network_table.NetworkTableID > 2
Note: The UserID column is a UNIQUE key.
To maintain the last field if required save a copy:
INSERT INTO network_table (MainID,UserID)
SELECT MainID,UserID FROM network_table ORDER BY NetworkTableID DESC LIMIT 1;
and then update the table:
UPDATE network_table
left join network_table as nt2 on nt2.NetworkTableID=network_table.NetworkTableID-1
SET network_table.UserID = nt2.UserID
WHERE network_table.NetworkTableID > 2

Extract the minimum positive value of each row in a matrix?

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).

combine multiple rows from the same table (days of the week)

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

MySQL order by 0 then largest

I am trying to do a mysql sort that displays 0 first and then by the largest number.
My current mysql statement returns
10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 0, 0
But I would like to get this
0, 0, 0, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1
Is it possible to build a MySQL query that orders an integer from largest to smallest with 0 at the beginning?
Try this order by statement:
order by val = 0 desc, val desc
The first part is a boolean that evaluates to "1" when the value is 1 and otherwise 0. The second orders the rest of the values in descending order.
you have to use 2 filters
select * from mytable
order by mycolumn=0 desc, mycolumn desc