MySQL get row when certain limit has been reached - mysql

I'm getting an headache of solving the following problem.
We are looking for a query where it retrieves a the data when the SUM(price_total) reached a certain level grouped by type. Table structures are as followed:
CREATE TABLE `Table1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`Date` datetime DEFAULT NULL,
`type` int(11) DEFAULT NULL,
`price_total` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1;
Data
INSERT INTO `Table1` (`id`, `Date`, `type`, `price_total`)
VALUES
(1,'2013-02-01 00:00:00',1,5),
(2,'2013-02-01 00:00:00',2,15),
(3,'2013-02-02 00:00:00',1,25),
(4,'2013-02-03 00:00:00',3,5),
(5,'2013-02-04 00:00:00',4,15),
(6,'2013-03-05 00:00:00',1,20),
(7,'2013-08-07 00:00:00',4,15);
Example outcome for threshold 15, in chronological order.
Type 1: 2013-02-02 00:00:00 Because here it came above 15. (15+5)
Type 2: 2013-02-01 00:00:00
Type 3: n/a SUM(price_total) < 15
Type 4: 2013-02-04 00:00:00
To sum up. I want to know the date that they crossed the threshold. Price total should be summed up in chronological order.

Here's a simple, self explanatory query:
select type, min(date) as date
from (
select t1.type, t1.date, sum(t2.price_total) as total
from table1 t1
join table1 t2
on t2.type = t1.type
and t2.date <= t1.date
group by t1.type, t1.date
having total >= 15
) sub
group by type
Demo: http://rextester.com/GMAK8269

Related

how insert registers of today from another table 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();

How to sum all the value in a specific date in mysql

i want to sum all the values in a specific date in mysql but idk what is the right syntax
CREATE TABLE `trans` (
`id` int(12) NOT NULL,
`date_sold` datetime NOT NULL,
`total` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
ALTER TABLE `trans`
ADD PRIMARY KEY (`id`);
ALTER TABLE `trans`
MODIFY `id` int(12) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=8;
id
date_sold
total
1
2021-02-23
12
2
2021-02-23
6
3
2021-02-24
32
4
2021-02-24
10
now i want to sum all the values in that specific date
ex:
id
date
total
1
2021-02-23
18
2
2021-02-24
42
is that possible?
Alternative Use of ROW_NUMBER() function. Because ROW_NUMBER() isn't supported in below v5.8. First calculate date wise total and then apply id incrementally.
-- MySQL(5.6)
SELECT (#row_number:= #row_number + 1) id
, t.date_sold, t.total
FROM (SELECT date_sold
, SUM(total) total
FROM trans
GROUP BY date_sold ) t, (SELECT #row_number := 0) x
ORDER BY t.date_sold
Please check from URL https://dbfiddle.uk/?rdbms=mysql_5.6&fiddle=5cc2305b465ac2454be5bdb1a9e8af4a

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.

Mysql sort alphanumeric data

I have two tables tt1 and tt2 both contains same fields. I want to sort data by no from both table.
Table : tt1
CREATE TABLE IF NOT EXISTS `tt1` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`no` varchar(5) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
INSERT INTO `tt1` (`id`, `no`) VALUES
(1, '1A'),
(2, '3A'),
(3, '2A');
Table : tt2
CREATE TABLE IF NOT EXISTS `tt2` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`no` varchar(5) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
INSERT INTO `tt2` (`id`, `no`) VALUES
(1, '2A'),
(2, '3A'),
(3, '1A');
Expected output
ID | No
========
1 | 1A
3 | 1A
1 | 2A
3 | 2A
2 | 3A
2 | 3A
I want to ascending order of no field from both table as given output how I can get.
SQLFiddle
In this case using order by after every select is wrong (won't return desired output), because that will order both row-sets separately and union them after that.
What you want here is to order already combined data, therefore you should be using order by only once, after mysql makes union of tables (i.e. combines), because once it combines tables it has all data together but unordered, so when mysql sees order by it orders whole data for you.
Sample:
select * from `tt1`
union all
select * from `tt2`
order by `no`
Note: I've noticed you have wrong syntax in your fiddle. You need to add parentheses:
(select * from tt1 order by no)
union
(select * from tt2 order by no)
Note 2: Thanks #AlmaDo's notice. You should not use * with union queries. Because modification of your tables columns will break query. Use column names that you actually need. E.g. query in sample becomes:
select `id`, `no` from `tt1`
union all
select `id`, `no` from `tt2`
order by `no`

MySQL innoDB: Long time of query execution

I'm having troubles to run this SQL:
I think it's a index problem but I don't know because I dind't make this database and I'm just a simple programmer.
The problem is, that table has 64260 records, so that query gets crazy when executing, I have to stop mysql and run again because the computer get frozen.
Thanks.
EDIT: table Schema
CREATE TABLE IF NOT EXISTS `value_magnitudes` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`value` float DEFAULT NULL,
`magnitude_id` int(11) DEFAULT NULL,
`sdi_belongs_id` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`reading_date` datetime DEFAULT NULL,
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1118402 ;
Query
select * from value_magnitudes
where id in
(
SELECT min(id)
FROM value_magnitudes
WHERE magnitude_id = 234
and date(reading_date) >= '2013-04-01'
group by date(reading_date)
)
EDIT2
First, add an index on (magnitude_id, reading_date):
ALTER TABLE
ADD INDEX magnitude_id__reading_date__IX -- just a name for the index
(magnitude_id, reading_date) ;
Then try this variation:
SELECT vm.*
FROM value_magnitudes AS vm
JOIN
( SELECT MIN(id) AS id
FROM value_magnitudes
WHERE magnitude_id = 234
AND reading_date >= '2013-04-01' -- changed so index is used
GROUP BY DATE(reading_date)
) AS vi
ON vi.id = vm.id ;
The GROUP BY DATE(reading_date) will still need to apply the function to all the selected (thorugh the index) rows and that cannot be improved, unless you follow #jurgen's advice and split the column into date and time columns.
Since you want to get results for every day you need to extract the date from a datetime column with the function date(). That makes indexes useless.
You can split up the reading_date column into reading_date and reading_time. Then you can run the query without a function and indexes will work.
Additionally you can change the query into a join
select *
from value_magnitudes v
inner join
(
SELECT min(id) as id
FROM value_magnitudes
WHERE magnitude_id = 234
and reading_date >= '2013-04-01'
group by reading_date
) x on x.id = v.id
For starters, I would change your query to:
select * from value_magnitudes where id = (
select min(id) from value_magnitudes
where magnitude_id = 234
and DATE(reading_date) >= '2013-04-01'
)
You don't need to use the IN clause when the subquery is only going to return one record.
Then, I would make sure you have an index on magnitude_id and reading_date (probably a two field index) as that's what you are querying against in the subquery. Without that index, you are scanning the table each time.
Also if possible change magnitude_id and reading_date to non null. Null values and indexes are not great fits.