SQL - insert new row depends on previous data from same table - mysql

I have a table with Car name. Here is a pseudo-table :
This table has been fallen with data like :
order = 14214
type = 0
created = 2017-12-10 23:39:23
I want to some operation with this data :
1 - find data till 6 days ago.
2 - (For each records of step 1)
I want to insert new record with order same as step1.order and with type= 1.
For first step , I found out I use
select *
from cars
WHERe `created` <= Date(Now()) - INTERVAL 6 day
but for next step, Is there any suggestion?
EDITED: :
Ex . I had a table with 250 records, after inserting new data, my table would be 500 rows with A table and A' (B&B',...) for each order.

You can try as below script.
Note: I assume ID field is auto-increment primary key.
insert into cars (`order`, type, created)
select `order`, 1 type, created
from cars
WHERe `created` <= Date(Now()) - INTERVAL 6 day
Hope it can help.

Related

Select one piece of data from every day at a specific hour MySQL

My database has data imputed every 1 minute and is stored in the format 2020-04-05 16:20:04 under a column called timestamp.
I need a MySQL query to select data from every day at a specific hour (the second does not matter), for for example I want to get the data from 16:00 of every day from the past 30 days.
It currently, just grabs the data from the past 30 days and then the PHP application sorts it, however, this is causing very slow loading time, hence wanting to only select the wanted data from the database.
Example of data
Please try the following sql:
select
d.timestamp, hour(d.timestamp)
from
demo1 d
where
DATEDIFF(NOW(), d.timestamp) < 30 and hour(d.timestamp) = 16;
The create sql is as following:
CREATE TABLE `demo1` (
`id` int(11) not null auto_increment primary key,
`serverid` int(11) not null,
`timestamp` datetime not null,
KEY `idx_timestamp` (`timestamp`)
) engine = InnoDB;
insert into `demo1` (serverid, timestamp)
VALUES (1, "2020-07-05 16:20:04"),
(2, "2020-07-06 17:20:04"),
(3, "2020-07-07 16:40:04"),
(4, "2020-07-08 08:20:04"),
(5, "2020-07-05 15:20:04"),
(5, "2020-07-05 16:59:04"),
(5, "2020-06-04 16:59:04");
Zhiyong's response will work, but wont perform well. You need to figure out a way to get the query to use indexes.
You can add a simple index on timestamp and run the query this way:
SELECT
d.timestamp, d.*
FROM demo1 d
WHERE 1
AND d.timestamp > CURDATE() - INTERVAL 30 DAY
AND hour(d.timestamp) = 16;
In MySQL 5.7 and up, you can created a generated column (also called calculated column) top store the hour of the timestamp in a separate column. You can then index this column, perhaps as a composite index of hour + timestamp, so that the query above will perform really quickly.
ALTER TABLE demo1
ADD COLUMN hour1 tinyint GENERATED ALWAYS AS (HOUR(timestamp)) STORED,
ADD KEY (hour1, timestamp);
The result query would be:
SELECT
d.timestamp, d.*
FROM demo1 d
WHERE 1
AND d.timestamp > CURDATE() - INTERVAL 30 DAY
AND hour1 = 16;
More info on that here:
https://dev.mysql.com/doc/refman/5.7/en/create-table-generated-columns.html
https://dev.mysql.com/doc/refman/5.7/en/generated-column-index-optimizations.html

how to update a sql database table based on the condition from another table in the same database

I have a two tables in a database.
table_1(device_ID, date,voltage)
table_2(device_ID,device_status)
I am trying to create an event to execute every 5 minutes.
What I am trying to achieve is, select device_ID from table_1 if there is no new data over the last 10 minutes and update the table_2, that means set device_status to 0.
How do i pass conditions between two tables?
BEGIN
select device_ID from table_1 where date = DATE_SUB(NOW(), INTERVAL 10 Minutes);
//here i will get device_IDs if there was a data within last 10 minutes.
//but i need device_ID if there were no data.
//how to update table_2 based on the above condition?
END
You can use the results of your first query as a subquery to de-select rows (by using NOT IN) for the UPDATE:
UPDATE table2
SET device_status = 0
WHERE device_ID NOT IN (select device_ID
from table_1
where date > DATE_SUB(NOW(), INTERVAL 10 Minutes))
Note I think you probably want >, not = in your where condition in the subquery.

MySQL - Average values of data for every 3 hours?

I currently have two tables in mysql that are collecting data. One collects every 3 hours and the other every 15 minutes. I am trying to create a forecast using this data using machine learning techniques which requires the data to be of the same time interval.
My question is, how can I get the average value for every 3 hours from both tables into a new table that organises them by date and hour? So of a format like:
Date / Hour / Table 1 3-hour average / Table 2 3-hour average
Table 1 (every 3 hours):
datetime(timestamp)/level(double)
Table 2 (every 15 minutes):
datetime(timestamp)/value(double)
I have managed to create a table that gives me the average per day, but I'd prefer something more accurate!
This is the statement I've already got for daily averages:
SELECT DAY(`datetime`),
AVG(`level`) AS `Table 1 Average` ,
(SELECT AVG(`value`) AS `Table 2 Daily Average`
FROM `table2`
WHERE DAY(`datetime`) = DAY(table1.datetime)
GROUP BY DAY(`datetime`))
FROM `table1` GROUP BY DAY(`datetime`);
Thanks!
You really just need to change the subquery. I think this may do way you want:
SELECT t1.*,
SELECT AVG(t2.`value`)
FROM `table2`
WHERE t2.datetime <= t1.datime and
t2.datetime >= date_sub(t1.datetime, interval 3 hour)
) as t2_moving_average
FROM `table1` t1;

How to select the field's increment from mysql

I have a table recording the accumulative total visit numbers of some web pages every day. I want to fetch the real visit numbers in a specific day for all these pages. the table is like
- record_id page_id date addup_number
- 1 1 2012-9-20 2110
- 2 2 2012-9-20 1160
- ... ... ... ...
- n 1 2012-9-21 2543
- n+1 2 2012-9-21 1784
the result I'd like to fetch is like:
- page_id date increment_num(the real visit numbers on this date)
- 1 2012-9-21 X
- 2 2012-9-21 X
- ... ... ...
- N 2012-9-21 X
but I don't want to do this in php, cause it's time consuming. Can I get what I want with SQL directives or with some mysql functions?
Ok. You need to join the table on itself by joining on the date column and adding a day to one side of the join.
Assuming:
date column is a legitimate DATE Type and not a string
Every day is accounted for each page (no gaps)
addup_number is an INT of some type (BIGINT, INT, SMALLINT, etc...)
table_name is substituted for your actual table name which you don't indicate
Only one record per day for each page... i.e. no pages have multiple counts on the same day
You can do this:
SELECT t2.page_id, t2.date, t2.addup_number - t1.addup_number AS increment_num
FROM table_name t1
JOIN table_name t2 ON t1.date + INTERVAL 1 DAY = t2.date
WHERE t1.page_id = t2.page_id
One thing to note is if this is a huge table and date is an indexed column, you'll suffer on the join by having to transform it by adding a day in the ON clause, but you'll get your data.
UPDATED:
SELECT today.page_id, today.date, (today.addup_number - yesterday.addup_number) as increment
FROM myvisits_table today, myvisits_table yesterday
WHERE today.page_id = yesterday.page_id
AND today.date='2012-9-21'
AND yesterday.date='2012-9-20'
GROUP BY today.page_id, today.date, yesterday.page_id, yesterday.date
ORDER BY page_id
Something like this:
SELECT date, SUM(addup_number)
FROM your_table
GROUP BY date

Padding MYSQL data with missing dates when comparing year over year stats?

I have a table that tracks emails sent. It is pretty simple.
ID | DATETIME | E-MAIL | SUBJECT | MESSAGE
I have been collecting data for several years. Some days I don't have any entries in the table.
query1:
SELECT COUNT(ID) FROM emails
WHERE DATE(datetime) >= 'XXXX-XX-XX'
AND DATE(datetime) is <= 'ZZZZ-ZZ-ZZ'
GROUP BY DATE(datetime)
I then use a some php to get one year prior for both XXXX and YYYY and run the second query which is the same as the first...
query2:
SELECT COUNT(ID) from emails
WHERE DATE(datetime) >= 'XXXX-XX-XX'
AND DATE(datetime) is <= 'ZZZZ-ZZ-ZZ'
GROUP BY DATE(datetime)
I am using a charting package to compare how many emails I got for a date range and then I overlay how many emails I got for the same range only one year prior. This is two queries right now and I chart the results.
The issue is where mysql does not have any emails for 2011 for a day in question, but has a few in 2012 for the same day.
Combining the results and graphing them skews the results since I am missing a date and a 0 value for last year for that day, effectively making all my values no longer match up.
2011-03-01 10 2012-03-01 4
2011-03-02 4 2012-03-02 2
2011-03-03 6 2012-03-04 1 <---- see where the two queries
end up diverging? (I had nothing
logged for 2012-03-03 so naturally
it was not in the results.
Is there a way I can get mysql to output the data I need including dates where value appear in one year but not another OR if no values appear in either year (still need date and 0) so my chart works?
I cannot seem to figure out how to do this...
Thanks!
There are a few different ways to get the results for a contiguous set of dates. My favourite one is to create the full set that is required using a dummy table or an existing contiguous set of ids from an AI PK. Something like this -
SELECT '2011-01-01' + INTERVAL (id -1) DAY
FROM dummy
WHERE id BETWEEN 1 AND 365
This will return a full set of days for 2011 which can then be LEFT JOINed to your emails table to get the counts -
SELECT `dates`.`date`, COUNT(emails.id)
FROM (
SELECT '2011-01-01' + INTERVAL (id - 1) DAY AS `date`, '2011-01-01 23:59:59' + INTERVAL (id - 1) DAY AS `end_of_day`
FROM dummy
WHERE id BETWEEN 1 AND 365
) `dates`
LEFT JOIN emails
ON `emails`.`datetime` BETWEEN `dates`.`date` AND `dates`.`end_of_day`
GROUP BY `dates`.`date`
To populate your dummy / seq table you can insert the first ten values manually and then use INSERT ... SELECT to add the rest -
CREATE TABLE dummy (id INTEGER NOT NULL PRIMARY KEY);
INSERT INTO dummy VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
SET #tmp := (SELECT MAX(id) FROM dummy) + 1;
INSERT INTO dummy
SELECT #tmp + id
FROM dummy;
You need to execute the SET query before each run of the INSERT ... SELECT query.