MySQL : find repeating events that are outdated - mysql

I've looked for solutions but couldn't find anything for my specific problem and can't manage to sort it on my own, the queries I'm trying are too heavy and timeout my server.
I have a table 'events' like this :
+-----------+--------------------------------+
| field | informations |
+-----------+--------------------------------+
| id | INT(11) PRIMARY AUTO_INCREMENT |
| repeat_id | INT(11) |
| timestamp | TIMESTAMP |
| title | VARCHAR(255) |
| details | TEXT |
+-----------+--------------------------------+
My events cane be unique ('repeat_id'=0) or repeated ('repeat_id'>0), and my problem is, I want to find all "outdated" events, that is to say the events that are repeated AND whose max timestamp is under current timestamp.
It might be easy using the good synthax and/or functions but I can't manage to do it... any help would be appreciated!
Thanks a lot,
Arthur

What if you try like below
select * from events
where repeat_id > 0
group by title
having max(`timestamp`) <= CURRENT_TIMESTAMP;

Related

MySQL: selecting dates (from timestamp) for which condition (related to other fields in the row) is fulfilled

My SQL knowledge is rather weak and I come from procedural programming, so bear with me. I have a database that contains data from a weather station - these are collected each minute and the (important part of the) table is
MariaDB [weather]> describe readings;
+------------------+------------+------+-----+-------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------------+------------+------+-----+-------------------+-------+
| time | timestamp | NO | PRI | CURRENT_TIMESTAMP | |
| inside_temp | float | YES | | NULL | |
| outside_temp | float | YES | | NULL | |
+------------------+------------+------+-----+-------------------+-------+
I want to find all days where the outside_temp was not lower and not larger than some values.
I can code it externally using MySQL for queries like
select min(outside_temp), max(outside_temp) from readings where date(time)='2022-01-27';
and iterating over all days in the database to check temperature values for each day separately, but I wonder if it is possible to do the selection just using MySQL command (I suppose it is, just beyond my imagination).
Something like select date(time), min(outside_temp), max(outside_temp) from readings group by date(time); would give you all timestamps that meet the requirements

Best way to weekly update a MYSQL field?

I want to weekly update a field in a MySQL table "Persons", with the avg of two fields of the "Tasks" table, end_date and start_date:
PERSON:
+----------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+-------------+------+-----+---------+-------+
| average_speed | int(11) | NO | | 0 | |
+----------------+-------------+------+-----+---------+-------+
TASKS:
+----------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+-------------+------+-----+---------+-------+
| person_id | int(11) | NO | | NULL | |
| start_date | date | NO | | NULL | |
| end_date | date | NO | | NULL | |
+----------------+-------------+------+-----+---------+-------+
(tables are not complete).
average_speed = AVG(task.end_date - task.start_date)
Now, the Tasks table is really big, and ** I don't want to compute the average on every task for every person every week**. (That's a solution, but I'm trying to avoid it).
What's the best way to update the average_speed?
I thought about adding two columns in the person's table:
"last_count": count of computed tasks since now for each person
"last_sum": last sum of (end_date - start_date) for each person
So that on a new update i could do something like average_speed = (last_sum+new_sum) / (last_count + new_count) where new_count is the sum of the tasks in the last week.
Is there a better solution/architecture?
EDIT:
to answer a comment, the query I would do is something like this:
SELECT
count(t.id) as last_count,
sum(TIMESTAMPDIFF(MINUTE, t.start_date, t.end_date)) as last_sum
avg(TIMESTAMPDIFF(MINUTE, t.start_date, t.end_date))
from tasks as t
where t.end_date BETWEEN DATE_SUB(CURDATE(), INTERVAL 1 WEEK) AND CURDATE()
And i can rely on a php script to get result and do some calculations
Having a periodic update to the table is a bad way to go for all the reasons you've listed above, and others.
If you have access to the code that writes to the Tasks table, that’s the best place to put the update. Add an Average field and calculate and set the value when you write the task end time.
If you don’t have access to the code, you can add a calculated field to the table that shows the average and let SQL figure it out during the execution of a query. This can slow queries down a little, but the data is always valid and SQL is smart enough to only calculate that value when it is needed.
A third (ugly) option is a trigger on the table that updates the value when appropriate. I’m not a fan of triggers because they hide business logic in unexpected places, but sometimes you just have to get the job done.

PuTTY outputs weird stuff when selecting in MySQL

I've encountered a strange problem when I was using PuTTY to query the following MySQL command: select * from gts_camera
The output seems extremely weird:
As you can see, putty outputs loads of "PuTTYPuTTYPuTTY..."
Maybe it's because of the table attribute set:
mysql> describe gts_kamera;
+---------+----------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+----------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| datum | datetime | YES | | CURRENT_TIMESTAMP | |
| picture | longblob | YES | | NULL | |
+---------+----------+------+-----+-------------------+----------------+
This table stores some big pictures and their date of creation.
(The weird ASCII-characters you can see on top of the picture is the content.)
Does anybody know why PuTTY outputs such strange stuff, and how to solve/clean this?
Cause I can't type any other commands afterwards. I have to reopen the session again.
Sincerely,
Michael.
The reason this happens is because of the contents of the file (as you have a column defined with longblob). It may have some characters that Putty will not understand, therefore it will break as it is happening with you.
There is a configuration that may help though.
You can also not select every column in that table (at least not the *blob ones) as:
select id, datum from gts_camera;
Or If you still want to do it use the MySql funtion HEX:
select id, datum, HEX(picture) as pic from gts_camera;

Exclude rows in mysql which contain a year without the NOT LIKE operator

I have a table which contains tags. Almost all tags are genres (such as action and comedy). However there are also tags such as Winter 2014 and Summer 2012. These are seasonal tags.
I want to exclude those tags from a genre listing. So how do I exclude those seasonal tags in the query?
The reason I don't want to use the NOT LIKE operator is to prevent full table scans.
This is what I currently have (in eloquent):
$genres = Tag::where('slug', 'not like', '%20%')->get()->lists('name');
Sidenote: a laravel 4 (eloquent) approach would be appreciated but not necessary.
This is my table
+---------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| slug | varchar(255) | NO | MUL | NULL | |
| name | varchar(255) | NO | | NULL | |
| suggest | tinyint(1) | NO | | 0 | |
| count | int(10) unsigned | NO | | 0 | |
+---------+------------------+------+-----+---------+----------------+
If I were you, I would add seasonal tinyint(1) field to this table and now you could simply run:
$genres = Tag::whereSeasonal(0)->get()->lists('name');
to get tags that are not seasonal.
If you cannot do it, you could store ids of seasonal tags in PHP array (or in one more table) - I don't know how many tags you have and how often you add seasonal tags and then you could get non-seasonal tags:
$genres = Tag::whereNotIn('id', $arrayOFSesonalIds)->get()->lists('name');
If you're looking for a solution to exclude years in data fields that are stored as strings (CHAR/VARCHAR), NOT LIKE is probably the best way to go about it going off of your description of the problem. If the dates you're checking are DATE/DATETIME/TIMESTAMP you can use the YEAR() MySQL function to yank the year out of the field to which you wish to compare.
If not, could you provide the output of DESCRIBE tablename for the table on which you wish to perform this action?

Adding value obtained from another table to all rows

I have two tables one called slotLength and one called schedule. Here are their descriptions:
+------------+------+------+-----+----------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+------+------+-----+----------+-------+
| slotLength | time | NO | PRI | 00:00:00 | |
+------------+------+------+-----+----------+-------+
+-----------+-------------+------+-----+----------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+----------+----------------+
| dayId | int(1) | NO | PRI | NULL | auto_increment |
| dayName | varchar(15) | YES | | NULL | |
| startHour | time | YES | | 08:00:00 | |
+-----------+-------------+------+-----+----------+----------------+
I know that they do not have the best design, but I am still learning. Also, they are just an experiment so please ignore the mistakes in their desigin.
Before I proceed, let's assume that slotLenght table contains just one row and let's call it's value slotSize.
I want to compute startHour + slotSize * n, where startHour represents values from startHour column in schedule table and n is a number. To be more specific, let's see an example,
if slotSize is "01:00:00" and a value from startHour is "09:00:00", then startHour +
slorSize * 3 I expect to have the value "12:00:00".
How the query should look like? Thank you.
I'm not sure you can multiply against a time field in SQL. Adding and subtracting is fairly easy, but multiplication would get a bit more complicated. You can use ADDTIME() for part of the equation, but I'm unsure of the multiplication part. Some heavier mathematics might have to come into play for that.
Here is a list of MySQL time functions
http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html
EDIT:
Perhaps something along the lines of converting to seconds, multiplying, and then converting back would work. I'm not overly familiar with MySQL so hopefully someone will give you the query your looking for, but this should get you started to try on your own.
SELECT ADDTIME(startHour, SEC_TO_TIME(TIME_TO_SEC(slotSize) * 3)) AS Calculated
FROM Table, OtherTable
Not sure if ^ Table is needed so if it works without it forget if not throw it in there to select startHour.
I believe this is close to what your looking for. As I said being unfamiliar with MySQL errors most likely lie in wait especially with the ADDTIME() function as I believe it requires the date portion to work.