how insert registers of today from another table mysql - mysql

I'm trying to count the records in my "records" table and insert in results table but I just want to count today's records.
Below you will see some alternatives that I tried (I'm using MySQL), but I keep getting this error:
You have a syntax error in your SQL next to '' on line 2
INSERT INTO results (Data,total)
VALUES (now(), (SELECT COUNT(*) FROM records WHERE Data = now());
This SQL also causes an error:
INSERT INTO results (Data, total)
VALUES (now(), (SELECT COUNT(record.ID) AS day FROM record
WHERE date(Data) = date(date_sub(now(), interval 0 day));
and then
INSERT INTO resultS (Data,total)
VALUES (now(), (SELECT COUNT(*) FROM records
WHERE Data >= DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY));
And yet another attempt:
INSERT INTO results (Data, Total)
VALUES (now(), (SELECT COUNT(*) FROM records
WHERE DATE(Data)= CURRENT_DATE() - INTERVAL 1 DAY));
This is my sql config man:
CREATE TABLE `records`
(
`ID` char(23) NOT NULL,
`Name` varchar(255) NOT NULL,
`Total` int(255) NOT NULL,
`Data` date NOT NULL,
`QrCode` varchar(255) NOT NULL,
`City` varchar(255) NOT NULL,
`Device` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `results`
(
`id` int(11) NOT NULL,
`total` int(11) NOT NULL,
`Data` date DEFAULT NULL,
`grown` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

You have defined grown column as not null so you cannot put there NULL.
My query works :
INSERT INTO results
VALUES (1, (SELECT COUNT(1) FROM records WHERE Data= now()), now(), 1);
You should define default value for grown column. Same situation you have with column id. You should define sequence for column id:
id NOT NULL AUTO_INCREMENT;

INSERT INTO results (Data, total)
SELECT CURRENT_DATE(), COUNT(*)
FROM records
WHERE DATE(Data) = CURRENT_DATE();

Related

Max from joined table based on value from first table

I have 2 tables.
First holds job details, second one the history of those job runs. First one also contains job period, per customer which is minimum time to wait before running next job for same customer. The time comparison needs to happen on started_on field of second table.
I need to find out the job ids to run next.
Schemas
job_details table
CREATE TABLE `job_details` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`customer_id` varchar(128) NOT NULL,
`period_in_minutes` int(11) unsigned NOT NULL,
`status` enum('ACTIVE','INACTIVE','DELETED') DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
job_run_history table
CREATE TABLE `job_run_history` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`job_id` int(10) unsigned NOT NULL,
`started_on` timestamp NULL DEFAULT NULL,
`status` enum('STREAMING','STREAMED','UPLOADING','UPLOADED','NO_RECORDS','FAILED') DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_job_id` (`job_id`),
CONSTRAINT `fk_job_id` FOREIGN KEY (`job_id`) REFERENCES `job_details` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Sample data for job_details table:
INSERT INTO `job_details` (`id`, `customer_id`, `period_in_minutes`, `status`)
VALUES
(1, 'cust1', 1, 'ACTIVE'),
(2, 'cust2', 1, 'ACTIVE'),
(3, 'cust3', 2, 'ACTIVE');
Sample data for job_run_history table:
INSERT INTO `job_run_history`(`job_id`, `started_on`, `status`)
VALUES
(1, '2021-07-01 14:38:00', 'UPLOADED'),
(2, '2021-07-01 14:37:55', 'UPLOADED');
Expected output (When run at 2021-07-01 14:38:56):
id
2,3
id => 1 did NOT get selected because the last job started within last 1 minute
id => 2 DID get selected because the last job started more than last 1 minute ago
id => 3 DID get selected because it has no run history
I have tried this, but this doesn't compare with max of start_time, hence, doesn't work:
select jd.id, max(jrh.started_on) from job_details jd
left join job_run_history jrh on jrh.job_id=jd.id
where
jd.status='ACTIVE'
and (jrh.status is null or jrh.status not in ('STREAMING','STREAMED','UPLOADING'))
and (jrh.`started_on` is null or jrh.`started_on` < date_sub(now(), interval jd.`period_in_minutes`*60 second))
group by jd.id;
MySql Version: 5.7.34
Any help please? Thanks in advance..
I'd prefer to use UNION ALL (it must be more fast than one complex query):
-- the subquery for the rows which have matched ones in 2nd table
SELECT t1.id
FROM job_details t1
JOIN job_run_history t2 ON t1.id = t2.job_id
WHERE t1.status = 'ACTIVE'
AND t2.status not in ('STREAMING','STREAMED','UPLOADING')
AND CURRENT_TIMESTAMP - INTERVAL t1.period_in_minutes MINUTE > t2.started_on
UNION ALL
-- the subquery for the rows which have no matched ones in 2nd table
SELECT id
FROM job_details t1
WHERE NOT EXISTS ( SELECT NULL
FROM job_run_history t2
WHERE t1.id = t2.job_id )
AND status = 'ACTIVE';
https://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=8dcad95bf43ce711fdf40deda627e879
select jd.id from job_details jd
left join job_run_history jrh on jd.id= jrh.job_id
where jd.status = 'ACTIVE'
group by jd.id
having
max(jrh.started_on) < current_timestamp - interval max(jd.period_in_minutes) minute
or
max(jrh.id) is null
I'm not sure what's this filter about since you didn't explain it in your question so I didn't put it in the query: jrh.status not in ('STREAMING','STREAMED','UPLOADING'). However, I'm sure you can implement it in the query I posted.

Column count doesn't match value count at row 1 in MySQL

I have created a table with the following query:
CREATE TABLE `dailydata` (
`id` int(9) NOT NULL,
`Date` varchar(100) NOT NULL,
`EmpID` varchar(100) NOT NULL,
`name` varchar(100) NOT NULL,
`TeamName` varchar(100) NOT NULL,
`active` varchar(100) NOT NULL,
`idle` double NOT NULL,
`Stime` double NOT NULL,
`Etime` varchar(100) NOT NULL,
`Inofficehr` decimal(20,2) NOT NULL,
`activehr` double(19,2) NOT NULL,
`idlehr` double(19,2) NOT NULL,
`Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE
CURRENT_TIMESTAMP) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Set Primary key For 'id' column:
ALTER TABLE `dailydata`ADD PRIMARY KEY (`id`);
Now I'm trying to insert the data with this code:
INSERT INTO dailydata
SELECT A.Date, A.EmpID, B.name, B.TeamName,
SUM(CASE WHEN State = 'active' THEN A.MinutesatState ELSE 0 END) AS active,
SUM(CASE WHEN State = 'idle' THEN A.MinutesatState ELSE 0 END) AS idle,
Min(A.Statestarttime) AS Stime, MAX(A.StateEndtime) AS Etime,
ROUND((TIME_TO_SEC(MAX(A.StateEndtime))/60 -
TIME_TO_SEC(MIN(A.StateStarttime))/60)/60,2) as Inofficehr,
ROUND(SUM(CASE WHEN State = 'active' THEN A.MinutesatState ELSE 0 END)/60,2)
AS activehr,
ROUND(SUM(CASE WHEN State = 'idle' THEN A.MinutesatState ELSE 0 END)/60,2)
AS idlehr
FROM time A join ttld.login B on A.EmpID=B.username
WHERE A.Date='01-01-2019' AND A.Statestarttime <>'' AND A.StateEndtime <>''
GROUP BY A.EmpID;
But I'm getting this error:
#1136 - Column count doesn't match value count at row 1
I understand I have not define the ID in my insert code and the reason for it is I want it to auto populate.
How can I modify my INSERT query code to do so...
You have 13 columns in your table, but only 11 in your select, which is why you are getting this error.
But first, to make your id column auto-populate, you need to declare it as AUTO_INCREMENT. You can change it with an ALTER TABLE command:
ALTER TABLE dailydata CHANGE id id INT AUTO_INCREMENT PRIMARY KEY
Since you have a default value for your Timestamp column you don't need to insert a value for that.
To resolve the error you are seeing, you need to modify your INSERT query to to match the number of columns being inserted to the data either by
(a) naming the columns you are inserting; or
(b) inserting NULL values for the columns with no values (id and Timestamp)
e.g. (a)
INSERT INTO dailydata (`Date`, `EmpID`, `name`, `TeamName`, `active`, `idle` ,`Stime`, `Etime`, `Inofficehr`, `activehr`, `idlehr`)
SELECT A.Date, A.EmpID, B.name, B.TeamName,
...
e.g. (b)
INSERT INTO dailydata
SELECT NULL AS id,
A.Date, A.EmpID, B.name, B.TeamName,
...
NULL AS Timestamp
FROM ...

MySQL compare timestamp gives error

I'm trying to write a SQL query but I keep getting an error and I have no clue on what could be wrong. I read the manual and searched a lot for it, but I can't get it working.
Query:
SELECT appid
FROM steam_app
ORDER BY last_update, appid
WHERE last_update < '2014-10-16 01:01:01'
This keeps giving an error SQL Error 1064, SQL syntax.
Now I know the error is on the WHERE line. Because if I remove it, all is well.
Solution: the problem is the order of WHERE and ORDER BY. WHERE should be above ORDER BY.
What I want in the end is a query like:
SELECT appid
FROM steam_app
ORDER BY last_update, appid
WHERE last_update < NOW() + INTERVAL 7 DAY
My database:
CREATE TABLE `steam_app` (
`appid` INT(10) UNSIGNED NOT NULL,
`name` VARCHAR(128) NULL DEFAULT NULL,
`type` VARCHAR(64) NULL DEFAULT NULL,
`header_image` VARCHAR(256) NULL DEFAULT NULL,
`last_update` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`last_change` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`appid`),
INDEX `type` (`type`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB;
Sample data
INSERT INTO `steam_app` (`appid`, `name`, `type`, `header_image`, `last_update`, `last_change`) VALUES (327400, 'Sid Meier\'s Colonization (Classic)', 'game', 'http://cdn.akamai.steamstatic.com/steam/apps/327400/header.jpg?t=1412883714', '2014-10-16 13:36:37', '2014-10-16 13:36:37');
INSERT INTO `steam_app` (`appid`, `name`, `type`, `header_image`, `last_update`, `last_change`) VALUES (327650, 'May’s Mysteries: The Secret of Dragonville', 'game', 'http://cdn.akamai.steamstatic.com/steam/apps/327650/header.jpg?t=1413366276', '2014-10-16 13:36:37', '2014-10-16 13:36:37');
INSERT INTO `steam_app` (`appid`, `name`, `type`, `header_image`, `last_update`, `last_change`) VALUES (327860, 'Salt', 'game', 'http://cdn.akamai.steamstatic.com/steam/apps/327860/header.jpg?t=1413399075', '2014-10-16 13:31:53', '2014-10-16 13:31:53');
You need to use the date_add function. Additionally, the order by clause comes after the where clause:
SELECT last_update, appid
FROM steam_app
WHERE last_update < DATE_ADD(NOW(), INTERVAL 7 DAY)
ORDER BY last_update, appid

Slow performance on MySQL 5.6 trigger

I have a large table with 80 million rows and a trigger that updates two other tables, all of which are TokuDB. The server is running Percona 5.6
CREATE TABLE `main` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`ip_addr` varchar(50) NOT NULL DEFAULT '',
`username` varchar(255) NOT NULL DEFAULT ''.
PRIMARY KEY (`id`),
) ENGINE=TokuDB;
The trigger code is
if NEW.ip_addr <> "" THEN
-- get the current oldest date
-- set #maxdate := now();
set #maxdate := (select lastseen from uniq_ip where data = NEW.ip_addr);
INSERT INTO uniq_ip (`data`, `total`, `lastseen`)
VALUES (NEW.ip_addr, 1, NEW.timestamp, #subnet)
ON DUPLICATE KEY UPDATE total = total + 1, lastseen = latest_date(NEW.timestamp, #maxdate);
end if;
-- get all values in one go, its indexed some query comes from index.
if NEW.username <> "" THEN
-- get the current oldest date
set #maxdate := (select lastseen from uniq_username where data = NEW.username);
INSERT INTO uniq_username (`data`, `total`, `lastseen`)
VALUES (NEW.username, 1, NEW.timestamp)
ON DUPLICATE KEY UPDATE total = total + 1, lastseen = latest_date(NEW.timestamp, #maxdate);
end if;
and the uniq_username and uniq_ip are
CREATE TABLE `uniq_ip` (
`data` varchar(42) NOT NULL,
`total` mediumint(4) unsigned NOT NULL DEFAULT '0',
`lastseen` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`data`),
KEY `idx_lastseen` (`data`,`lastseen`)
) ENGINE=TokuDB DEFAULT CHARSET=ascii;
CREATE TABLE `uniq_username` (
`data` varchar(255) CHARACTER SET latin1 NOT NULL,
`total` mediumint(4) unsigned NOT NULL DEFAULT '0',
`lastseen` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`data`),
KEY `idx_data_time` (`data`,`lastseen`)
) ENGINE=TokuDB DEFAULT CHARSET=utf8;
The problem is that a bulk insert under load works perfectly on the username part of the trigger when calculating the timeseen value. However the first part of the function to do the same on the uniq_ip table drops insert rate from 800/s to 30/s when it processes
set #maxdate := (select lastseen from uniq_ip where data = NEW.ip_addr);
If you set to the get now(), its fast (but not the correct result). uniq_username and uniq_ip have the same structure and indexes and the trigger slows right down regardless of which you process first (username or ip) but its only the above statement that slows the trigger down.
The problem below if the uniq_ip table is either TokuDB or InnoDB and the default charset makes no difference, neither does the insert statement being active or commented out. Latest_date() is a tiny function that returns the most recent datetime
Any ideas or tips?
Thanks
main.ip_addr is a latin1 and uniq_ip.data was casting as utf. Changing uniq_ip.data to latin1 improved the insert rate from 50 inserts/sec to 1000 inserts/sec. I guess that latin1->utf8 cast is a cpu killer

MySQL Select Records from 2 not-related Tables Ordering by Timestamp

I'd like to collect data from 2 different mysql tables ordering the result by a timestamp but without merging the columns of the 2 tables in a single row.
T_ONE(one_id,one_someinfo,one_ts)
T_TWO(two_id,two_otherinfo,two_ts)
Notice that the field two_otherinfo is not the same as one_someinfo, the only columns in common are id and timestamp.
The result should be a mix of the two tables ordered by the timestamp but each row, depending on the timestamp, should contain only the respective columns of the table.
For example, if the newest record comes from T_TWO that row should have the T_ONE one_someinfo column empty.
I just need to order the latest news from T_ONE and the latest messages posted on T_TWO so the tables are not related. I'd like to avoid using 2 queries and then merging and ordering the results by timestamp with PHP. Does anyone know a solution to this? Thanks in advance
This is the structure of the table
CREATE TABLE `posts` (
`id` int(10) unsigned NOT NULL auto_increment,
`fromid` int(10) NOT NULL,
`toteam` int(10) NOT NULL,
`banned` tinyint(1) NOT NULL default '0',
`replyid` int(15) default NULL,
`cont` mediumtext NOT NULL,
`timestamp` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
CREATE TABLE `stars` (
`id` int(10) unsigned NOT NULL auto_increment,
`daynum` int(10) NOT NULL,
`userid` int(10) NOT NULL,
`vote` tinyint(2) NOT NULL default '3',
`timestamp` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
INSERT INTO `posts` (`fromid`, `toteam`, `banned`, `replyid`, `cont`, `timestamp`) VALUES(5, 12, 0, 0, 'mess posted#1', 1222222220);
INSERT INTO `posts` (`fromid`, `toteam`, `banned`, `replyid`, `cont`, `timestamp`) VALUES(5, 12, 0, 0, 'mess posted#2', 1222222221);
INSERT INTO `posts` (`fromid`, `toteam`, `banned`, `replyid`, `cont`, `timestamp`) VALUES(5, 12, 0, 0, 'mess posted#3', 1222222223);
INSERT INTO `stars` (`daynum`, `userid`, `vote`, `timestamp`) VALUES(3, 160, 4, 1222222222);
INSERT INTO `stars` (`daynum`, `userid`, `vote`, `timestamp`) VALUES(4, 180, 3, 1222222224);
The result ordering by timestamp DESC should be the second record of table stars with timestamp 1222222224 then the third record of table posts with timestamp 1222222223 and following... Since the tables have got different fields from each other, the first row of the result should contain the columns of the table stars while the columns of table posts should be empty.
The columns of a UNION must be the same name and datatype on every row. In fact, declare column aliases in the first UNION subquery, because it ignores any attempt to rename the column in subsequent subqueries.
If you need the columns from the two subqueries to be different, put in NULL as placeholders. Here's an example, fetching the common columns id and timestamp, and then fetching one custom column from each of the subqueries.
(SELECT p.id, p.timestamp AS ts, p.fromid, NULL AS daynum FROM posts)
UNION
(SELECT s.id, s.timestamp, NULL, s.daynum, FROM stars)
ORDER BY ts DESC
Also put the subqueries in parentheses, so the last ORDER BY applies to the whole result of the UNION, not just to the last subquery.
SELECT one_id AS id, one_someinfo AS someinfo, one_ts AS ts
UNION
SELECT two_id AS id, two_someinfo AS someinfo, two_ts AS ts
ORDER BY ts
SELECT one_id AS id
, one_someinfo AS one_someinfo
, NULL AS two_someinfo
, one_ts AS ts
FROM t_ONE
UNION ALL
SELECT two_id
, NULL
, two_someinfo
, two_ts
FROM t_TWO
ORDER BY ts