I'm having some difficulties on applying certain conditions if a column is empty or not.
My table is as follows:
CREATE TABLE `meets` (
`id` INT,
`scheduled` VARCHAR(255),
`status` INT
);
INSERT INTO meets(id,scheduled,status) VALUES (1,'','1');
INSERT INTO meets(id,scheduled,status) VALUES (2,'','2');
INSERT INTO meets(id,scheduled,status) VALUES (2,'1613220631','3'); // in 30 minutes
INSERT INTO meets(id,scheduled,status) VALUES (2,'1644756631','3'); // 2022
What I did so far is next:
SELECT * FROM meets WHERE FROM_UNIXTIME(scheduled) BETWEEN DATE_SUB(NOW(), INTERVAL 30 MINUTE) AND DATE_SUB(NOW(), INTERVAL -30 MINUTE) ORDER BY `id` DESC
The above only selects the record that has a timestamp in the following/past 30 minutes.
Other than that record, I also need to select record id 1 because it has status == 1.
So basically
if scheduled column is empty, check for status to be 1 and select if true;
if scheduled column is timestamp, apply condition from the query posted above;
Any ideas? Thank you!
You could add the missing rows using union
SELECT *
FROM meets
WHERE FROM_UNIXTIME(scheduled)
BETWEEN DATE_SUB(NOW(), INTERVAL 30 MINUTE) AND DATE_SUB(NOW(), INTERVAL -30 MINUTE)
ORDER BY `id` DESC
UNION
select * from meets where scheduled = '' AND status = 1
Related
We had a MySQL query that selected records and was required to also show Sold records for 60days before being removed from the shown results.
Logic was such that after changing a record from some invStatus to 1 which equals sold, we would filter it from our records after 60 days.
The problem is that if the filter is applied in a single query even active records are getting dropped if they are not updated within that 60 day window.
So how to select all records and then only filter a subset of those records based on date interval?
Should I select ALL the Ids and then filter those that are status sold and then apply the date interval in a subquery or run two queries and concatenate the two?
UPDATE:
SQLFiddle created that shows (10) records.
The goal is to not lose any invStatus = 0 but filter invStatus records that = 1 by NOT returning them if Update_date is older than 60 days from today
There are (7) records that have a invStatus = 0 (not Sold)
and (3) records that have invStatus = 1 (Sold)
SELECT
tblinventory.invId,
tblinventory.`Update_date`,
tblinventory.invStatus
FROM
tblinventory
WHERE NOT (Update_date < NOW() - INTERVAL 60 DAY)
ORDER BYtblinventory.invId
results in (6) records
5 which are invStatus = 0
1 that is invStatus = 1
Should be
(7) invStatus 0’s as they ALL should be present
(1) invStatus = 1 that is within 60 days
SQLFiddle schema:
CREATE TABLE IF NOT EXISTS `tblinventory` (
`invId` int(4) NOT NULL,
`Update_date` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`invStatus` int(3) NOT NULL DEFAULT '0'
) DEFAULT CHARSET=utf8;
INSERT INTO `tblinventory` (`invId`,`Update_date`,`invStatus`)
VALUES
("3777","2019-08-06 00:00:00","1"),
("3782","2019-08-30 00:00:00","0"),
("3820","2019-04-04 00:00:00","0"),
("3821","2019-03-21 00:00:00","1"),
("3835","2019-02-20 00:00:00","0"),
("3836","2019-06-30 00:00:00","1"),
("4035","2019-08-25 00:00:00","0"),
("4036","2019-09-01 00:00:00","0"),
("4037","2019-09-01 00:00:00","0"),
("4038","2019-09-01 00:00:00","0");
Query:
SELECT
tblinventory.invId,
tblinventory.`Update_date`,
tblinventory.invStatus
FROM
tblinventory
WHERE NOT (Update_date < NOW() - INTERVAL 60 DAY) AND invStatus = 1
ORDER BY
tblinventory.invId
Comparative Query:
WHERE NOT (Update_date < NOW() - INTERVAL 60 DAY)
https://www.db-fiddle.com/f/3KuYDHgYaNtaB8mMuatrz2/0
I guess you need a simple UNION ALL clause. Presumably invStatus <> 1 means non sold entities, You can try below query -
SELECT
tblinventory.invId,
tblinventory.`Update_date`,
tblinventory.invStatus
FROM
tblinventory
WHERE `invStatus` = 0 OR (Update_date >= NOW() - INTERVAL 60 DAY)
ORDER BY
tblinventory.invId
I'm storing records in msyql where a resolve_by column has a unix timestamp.
I'm trying this query:
SELECT id FROM tickets WHERE FROM_UNIXTIME('resolve_by','%Y-%m-%d') = CURDATE()
The basic table structure is:
id|resolve_by|date_created
4, 1506092040, 1506084841
But this is returning 0 records. How can I get records where the unix timestamp value = today's date?
Thanks,
Changed query from :
SELECT id FROM tickets WHERE FROM_UNIXTIME('resolve_by','%Y-%m-%d') = CURDATE()
To:
SELECT id FROM tickets WHERE FROM_UNIXTIME(resolve_by,'%Y-%m-%d') = CURDATE()
It's working now.
In general you'll want to avoid using functions on the columns side of where conditions, as it will most probably disqualify your query to benefit from indexes.
Consider something like:
create table test_table ( id varchar(36) primary key, ts timestamp );
insert into test_table (id,ts) values('yesterday', current_timestamp - interval 1 day);
insert into test_table (id,ts) values('midnight', current_date);
insert into test_table (id,ts) values('now', current_timestamp);
insert into test_table (id,ts) values('next midnight', current_date + interval 1 day);
insert into test_table (id,ts) values('tomorrow', current_timestamp + interval 1 day);
create index test_table_i1 on test_table (ts);
select *
from test_table
where ts >= current_date
and ts < current_date + interval 1 day;
;
PS: you can also use
select *
from test_table
where ts between current_date and current_date + interval 1 day;
if you're not picky about excluding next midnight (between accepts both boundaries)
What is an efficient way to get all records with a datetime column whose value falls somewhere between yesterday at 00:00:00 and yesterday at 23:59:59?
SQL:
CREATE TABLE `mytable` (
`id` BIGINT,
`created_at` DATETIME
);
INSERT INTO `mytable` (`id`, `created_at`) VALUES
(1, '2016-01-18 14:28:59'),
(2, '2016-01-19 20:03:00'),
(3, '2016-01-19 11:12:05'),
(4, '2016-01-20 03:04:01');
If I run this query at any time on 2016-01-20, then all I'd want to return is rows 2 and 3.
Since you're only looking for the date portion, you can compare those easily using MySQL's DATE() function.
SELECT * FROM table WHERE DATE(created_at) = DATE(NOW() - INTERVAL 1 DAY);
Note that if you have a very large number of records this can be inefficient; indexing advantages are lost with the derived value of DATE(). In that case, you can use this query:
SELECT * FROM table
WHERE created_at BETWEEN CURDATE() - INTERVAL 1 DAY
AND CURDATE() - INTERVAL 1 SECOND;
This works because date values such as the one returned by CURDATE() are assumed to have a timestamp of 00:00:00. The index can still be used because the date column's value is not being transformed at all.
You can still use the index if you say
SELECT * FROM TABLE
WHERE CREATED_AT >= CURDATE() - INTERVAL 1 DAY
AND CREATED_AT < CURDATE();
You can use subdate to indicate "yesterday" and use date() to indicate that you want records where just the date part of the column matches. So:
SELECT *
FROM tablename
WHERE DATE(created_at) = SUBDATE(CURRENT_DATE(), INTERVAL 1 DAY)
Here is the same question with an answer. To summarize answer for you, use subdate() as suggested by Sajmon.
subdate(currentDate, 1)
using your table it should be.
select *
from tablename
where created_at between subdate(CURDATE(), 1)
and date (now() )
use:
subdate(current_date, 1)
it's awesome for your case!
SELECT subdate(current_date(), 1)
SELECT * FROM table
WHERE created_at >= subdate(current_date(), 1)
You can use this, just put tablename and columnName (Which Contain 2021/01/09 or 2022-01-11 14:56:07 etc)
select * from (TABLENAME) where DATE(columnNAME) = TODAY - 1;
I am trying to set up an event/scheduler to grab the last minutes worth of data every single minute of the day with phpmyadmin.
Some how it is missing data out, it picks up some of the data but misses some out.
Can anyone advise on how to tweak my queries or another way how to do this ?
Here are the queries/events I'm using . --
GET ALL DATA FROM TRANDATA WITHIN THIS DATE RANGE -
CREATE TABLE TABLE1 AS SELECT ID_NO, POS, DATE,
TIMESTAMP FROM TRANDATA WHERE DATE
BETWEEN '2014-11-01 00:00:00' AND NOW()
AND POS IN ('IW1','IW2','IW3','IW4','IW5');
SET EVENT TO KEEP BRINGING DATA OVER FROM TRANDATA EVERY MINUTE OF DAY
CREATE event TABLE1GENERATOR ON schedule every 1 minute do INSERT INTO
TABLE1(ID_NO,POS, DATE, TIMESTAMP) SELECT ID_NO,
POS, DATE FROM TRANDATA
WHERE DATE BETWEEN DATE_SUB(NOW(), INTERVAL 1 MINUTE) AND NOW() AND POS IN
('IW1','IW2','IW3','IW4','IW5');
CREATE SECOND TABLE AND FILTER ID_NO FOR FIRST DATE IT SEES (MIN)
CREATE TABLE TABLE1FILTERED AS SELECT TABLE1.*
FROM TABLE1
WHERE TABLE1.DATE BETWEEN '2014-11-01 00:00:00' AND NOW() and NOT EXISTS (
SELECT *
FROM TABLE1 T2_MIN
WHERE T2_MIN.ID_NO=TABLE1.ID_NO
AND T2_MIN.TIMESTAMP< TABLE1.TIMESTAMP
);
CREATE EVENT TO KEEP FILTERING DATA EVERY MINUTE -
CREATE event TABLE1FILTER ON schedule every 1 minute do INSERT INTO
TABLE1FILTERED (ID_NO, POS, DATE, TIME_STAMP) SELECT TABLE1.*
FROM TABLE1
WHERE TABLE1.DATE BETWEEN DATE_SUB(NOW(), INTERVAL 1 MINUTE) AND NOW()
and NOT EXISTS (
SELECT *
FROM TABLE1 T2_MIN
WHERE T2_MIN.ID_NO=TABLE1.ID_NO
AND T2_MIN.TIMESTAMP< TABLE1.TIMESTAMP
);
first of all, this is the query which creates the "player history"
it can be executed as often as you want and it will only create new history rows for the players if there is no history row for yesterday or if the values changed since the latest history entry in the past.
INSERT INTO `player_history` (`player_id`, `date`, `races`, `maps`, `playtime`, `points`)
SELECT `p`.`id`, DATE_SUB(NOW(), INTERVAL 1 DAY), `p`.`races`, `p`.`maps`, `p`.`playtime`, `p`.`points`
FROM `player` `p`
WHERE `p`.`playtime` IS NOT NULL
AND `p`.`playtime` > 0
AND (
SELECT `player_id`
FROM `player_history`^
WHERE `player_id` = `p`.`id`
AND (
`date` = DATE_SUB(NOW(), INTERVAL 1 DAY)
OR (
`date` < DATE_SUB(NOW(), INTERVAL 1 DAY)
AND `races` = `p`.`races`
AND `points` = `p`.`points`
AND `maps` = `p`.`maps`
AND `playtime` = `p`.`playtime`
)
)
ORDER BY `date` DESC
LIMIT 1
) IS NULL;
now the problem is i also want to cleanup the history table using a single query. this already selects all history entries older than 10 days but the latest. but i cant just like do DELETE instead of SELECT *.
SELECT *
FROM `player_history` `ph`
WHERE `date` < DATE_SUB(NOW(), INTERVAL 10 DAY)
AND `date` != (SELECT `date`
FROM `player_history`
WHERE `player_id` = `ph`.`player_id`
ORDER BY `date` DESC
LIMIT 1);
so is tehre a way to do what i want using a single delete query?
Your query looks right in my eyes but you don't have the interval in the subquery.
I would do this:
DELETE FROM player_history
WHERE date < DATE_SUB(NOW(), INTERVAL 10 DAY)
AND date != (
SELECT MAX(date) FROM player_history
WHERE date < DATE_SUB(NOW(), INTERVAL 10 DAY)
)
What's the error message from mysql?
Probably you can't do this in a single query because the documentation states:
Currently, you cannot delete from a table and select from the same table in a subquery.
As a workaround you could select the ids of the rows that have to be deleted into a temporary table and then use a multi-table delete statement to delete the records from the original table.