SQL query issue for a tv show table - mysql

I have a table structure:
CREATE TABLE `tv_series_intervals` (
`id_tv_series` int(11) NOT NULL,
`week_day` smallint(1) NOT NULL DEFAULT 1,
`show_time` TIMESTAMP NOT NULL)
week day in a format 1,2,3,4,5,6,7
show_time it's a converted time to timestamp, for example, 11-45 will convert to 1970-01-01 11:45:00
How can I get next id_tv_series depending on today's datetime?
Does anyone have an idea by what query can I do that?
One example:
TV show (with 1 ID) shows on Wednesday at 00:00 and today is Tuesday 23:59, it should return ID 1

can you change structure to
CREATE TABLE tv_series_intervals (
id_tv_series int(11) NOT NULL,
week_day smallint(1) NOT NULL DEFAULT 1,
show_time TIME NOT NULL)
or perhaps you can include the function to get time sorted by
select *,from_unixtime(show_time, '%h:%i:%s') time from tv_series_interval
order by time

You can use this query to achieve your goal.
Assume today is day 1 and the time is 1970-01-01 12:45:00.
(SELECT * from db WHERE show_time > '1970-01-01 12:45:00' AND week_day = 1
ORDER BY show_time LIMIT 1)
UNION ALL
(SELECT * from db WHERE week_day > 1 AND NOT EXISTS
(SELECT * from db WHERE show_time > '1970-01-01 12:45:00' and week_day = 1 ORDER BY show_time LIMIT 1)
ORDER BY week_day , show_time LIMIT 1)
UNION ALL
(SELECT * from db WHERE week_day < 1 and NOT EXISTS
(SELECT * from db WHERE show_time > '1970-01-01 12:45:00' AND week_day = 1 ORDER BY show_time LIMIT 1) AND NOT EXISTS
(SELECT * from db WHERE week_day > 1)
ORDER BY week_day , show_time LIMIT 1)
We check if we have the next id today if there wasn't any id today we check for the nearest id on other days.
In the third select we check if today is 7 and we have to roll back to 1 and check for the nearest id on day 1.
You can use float type instead of timestamp for column show_time that makes sense as well.
If I was you and could modify the backend. I store the next timestamp totally in the database it could reduce the complexity. (e.g. next tv show will be on 18-02-2022 12:10:00)

Related

mysql group by week , one month and three recent month

I have a table with column named started_at
I want to get statistics of new inserted row by last day , week , one month and three month .
the started_at column format is default MySQL timestamp which is string .
before posting this question , I try this querys
SELECT WEEK(`started_at`) , COUNT(*) AS nbr FROM users_in_bots WHERE `bot_id` = 5529 GROUP BY WEEK (`started_at`);
SELECT MONTH(`started_at`), COUNT(*) AS nbr FROM users_in_bots WHERE `bot_id` = 5529 GROUP BY MONTH(`started_at`);
and the result is not what I want .
I want get all statistics with just one query .
the table structure :
CREATE TABLE `users_in_bots` (
`user_id` bigint(20) NOT NULL,
`bot_id` bigint(20) NOT NULL,
`started_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp()
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
sample row :
INSERT INTO `users_in_bots` (`user_id`, `bot_id`, `started_at`) VALUES
(2314, 509492849, '2022-02-27 03:59:21'),
(28779, 210686266, '2022-03-03 21:51:38'),
(28779, 503513058, '2022-04-01 12:28:37'),
(28779, 515774720, '2022-03-25 08:25:16'),
(28779, 518099352, '2022-03-22 17:22:38'),
(28779, 519646468, '2022-03-04 22:02:02'),
(84588, 517141146, '2022-03-28 12:36:45'),
(87075, 509498849, '2022-02-27 03:59:21'),
(116264, 210509102, '2022-02-27 00:02:54'),
(116264, 212268136, '2022-02-27 00:29:06');
expected output ( what i wish to use in my application ):
new users in last 24 hour : 42
new users in last week : 532
new users in last month : 4568
and same with 3 and six month and all the time .
You can use conditional aggregation to get the results you want. For example:
SELECT SUM(started_at BETWEEN NOW() - INTERVAL 1 HOUR AND NOW()) last_hour,
SUM(started_at BETWEEN CURDATE() - INTERVAL 1 WEEK AND CURDATE()) last_week,
SUM(started_at BETWEEN CURDATE() - INTERVAL 1 MONTH AND CURDATE()) last_month,
SUM(started_at BETWEEN CURDATE() - INTERVAL 3 MONTH AND CURDATE()) last_3month,
SUM(started_at BETWEEN CURDATE() - INTERVAL 6 MONTH AND CURDATE()) last_6month
FROM users_in_bots
Output (for your sample data as of 2022-04-13):
last_hour last_week last_month last_3month last_6month
0 0 4 10 10
Demo on dbfiddle

SQL MAX datetime - 1 day

I want to do a comparison between two dates. The highest date (currently via MAX datetime) is working, but I can't get the day after the highest date to compare the data with.
I'm using the following to get the data of the highest available date:
SELECT `datetime`, `standardSubscriptionDuration`,
SUM(`activeStandardPriceSubscriptions`) AS OneMonthActiveStandard
FROM `Subscription_totals`
WHERE `standardSubscriptionDuration` = '1 Month'
AND `datetime` = (SELECT MAX(`datetime`) AS Date FROM `Subscription_totals`)";
I already tried:
(SELECT MAX(`datetime`) -1 AS Date
But this won't give the result. How am I able to get the data of yesterday and eventually compare them?
I think that you want the following date arithmetics:
WHERE
`standardSubscriptionDuration` = '1 Month'
AND `datetime` = (
SELECT MAX(`datetime`) - interval 1 day AS Date FROM `Subscription_totals`
)

Select data between timestamp x and timestamp y returned as z amount of rows (scaled down result set)

I'm trying to select data between 2 given timestamps returned as a given amount of rows.
There's 3 variables to take into account;
timestamp 1
timestamp 2
amount of data points
So far I have this (and that kinda works) but doesn't return the wanted amount of rows. In the query below I'm trying to select 250 records between 2019-07-14 and 2019-07-15, but it returns 48 rows.
SELECT
AVG(`value`) AS `avg`,
`createdAt` AS `dtime`,
`createdAt` * 1 AS `dtime_int`,
ROUND(
`createdAt` / (
(CONVERT('2019-07-15', DATETIME) - CONVERT('2019-07-14', DATETIME)
) / 250)
) AS `groupBy`
FROM `samples`
WHERE `createdAt` BETWEEN '2019-07-14' AND '2019-07-15'
GROUP BY `groupBy`
ORDER BY `dtime` DESC;
So I'm guessing this isn't the best approach. Any and all suggestions are welcome!
Edit: this is a test data set I'm using and where I'm keeping progress: samples.sql
You problem is probably the between. In all likelihood, createdAt is a datetime, so the time component interferes with what you want to do.
I strongly advise you to use direct comparisons. If you want both days, then:
WHERE createdAt >= '2019-07-14' AND
createdAt < '2019-07-16'
If you want only 2019-07-14:
WHERE createdAt >= '2019-07-14' AND
createdAt < '2019-07-15'
Splitting this into a given number of rows is not really possible. After all, all the timestamps could be the same and then how would you get different bins?
But you can split this into equal sized bins:
SELECT floor( (timestampdiff(second, '2019-07-15', createdat) /
timestampdiff(second, '2019-07-15', '2019-07-17')
) * 48
) as grp,
AVG(`value`) AS `avg`
FROM samples s
WHERE createdAt >= '2019-07-14' AND
createdAt < '2019-07-16'
GROUP BY grp
ORDER BY grp DESC;

How to query SQL on date AND time

My current table looks like this - Table is called "S"
DJ DATE
---- ------
test yyyy/mm/dd hh:mm:ss
I've worked up to the below SQL query
SELECT *
FROM `S`
WHERE `DATE` = '2017-02-27 17:00:00'
ORDER BY `S`.`DATE` DESC
LIMIT 0 , 1
Rather than having the set date and time though I would like to query based on the current date AND time. I'm using datetime type structure.
All I'm looking to do is query the current datetime to get the current name from the DJ row
Thanks!
You can use now() function to get the current datetime.
SELECT *
FROM `S`
WHERE `DATE` = now()
ORDER BY `S`.`DATE` DESC
LIMIT 0 , 1
If you want to get result for today's date, you can use curdate and date function
SELECT *
FROM `S`
WHERE date(`DATE`) = curdate()
ORDER BY `S`.`DATE` DESC
LIMIT 0 , 1
With mysql, you can use the CURRENT_TIMESTAMP() function.
SELECT *
FROM S
WHERE DATE = CURRENT_TIMESTAMP()
ORDER BY S.DATE DESC
LIMIT 0, 1
I think you want:
select s.*
from s
where date(date) = CURDATE() and
hour(date) = hour(NOW())
order s.date` DESC
limit 0, 1;

MySql -- Determine periods of missing data with query

I have a database that's set up like this:
(Schema Name)
Historical
-CID int UQ AI NN
-ID Int PK
-Location Varchar(255)
-Status Varchar(255)
-Time datetime
So an entry might look like this
433275 | 97 | MyLocation | OK | 2013-08-20 13:05:54
My question is, if I'm expecting 5 minute interval data from each of my sites, how can I determine how long a site has been down?
Example, if MyLocation didn't send in the 5 minute interval data from 13:05:54 until 14:05:54 it would've missed 60 minutes worth of intervals, how could I find this downtime and report on it easily?
Thanks,
*Disclaimer: I'm assuming that your time column determines the order of the entries in your table and that you can't easily (and without heavy performance loss) self-join the table on auto_increment column since it can contain gaps.*
Either you create a table containing simply datetime values and do a
FROM datetime_table d
LEFT JOIN your_table y ON DATE_FORMAT(d.datetimevalue, '%Y-%m-%d %H:%i:00') = DATE_FORMAT(y.`time`, '%Y-%m-%d %H:%i:00')
WHERE y.some_column IS NULL
(date_format() function is used here to get rid of the seconds part in the datetime values).
Or you use user defined variables.
SELECT * FROM (
SELECT
y.*,
TIMESTAMPDIFF(MINUTE, #prevDT, `Time`) AS timedifference
#prevDT := `Time`
FROM your_table y ,
(SELECT #prevDT:=(SELECT MIN(`Time`) FROM your_table)) vars
ORDER BY `Time`
) sq
WHERE timedifference > 5
EDIT: I thought you wanted to scan the whole table (or parts of it) for rows where the timedifference to the previous row is greater than 5 minutes. To check for a specific ID (and still having same assumptions as in the disclaimer) you'd have to do a different approach:
SELECT
TIMESTAMPDIFF(MINUTE, (SELECT `Time` FROM your_table sy WHERE sy.ID < y.ID ORDER BY ID DESC LIMIT 1), `Time`) AS timedifference
FROM your_table y
WHERE ID = whatever
EDIT 2:
When you say "if the ID is currently down" is there already an entry in your table or not? If not, you can simply check this via
SELECT TIMESTAMPDIFF(MINUTE, NOW(), (SELECT MAX(`Time`) FROM your_table WHERE ID = whatever));
So I assume you are going to have some sort of cron job running to check this table. If that is the case you can simply check for the highest time value for each id/location and compare it against current time to flag any id's that have a most recent time that is older than the specified threshold. You can do that like this:
SELECT id, location, MAX(time) as most_recent_time
FROM Historical
GROUP BY id
HAVING most_recent_time < DATE_SUB(NOW(), INTERVAL 5 minutes)
Something like this:
SELECT h1.ID, h1.location, h1.time, min(h2.time)
FROM Historical h1 LEFT JOIN Historical h2
ON (h1.ID = h2.ID AND h2.CID > h1.CID)
WHERE now() > h1.time + INTERVAL 301 SECOND
GROUP BY h1.ID, h1.location, h1.time
HAVING min(h2.time) IS NULL
OR min(h2.time) > h1.time + INTERVAL 301 SECOND