MySQL: search orders made since yesterday 3pm till today 4pm - mysql

I have table ORDERS where is stored data about orders with their status and the date of order. I would like to search all orders with specified status and which was made yesterday after 3pm untill today 4pm. The query will run in different times (10am, 3pm, 5 pm... regardless).
So on example: if I run the query today (13.05.2014) I would like to get all orders made from 2014-12-05 15:00:00 untill 13-05-2015 16:00:00
The date is stored in format: YYYY-MM-DD HH:MM:SS
What I got is:
select *
from orders
where status = 'new'
and (
(
date_add(created_at, INTERVAL 1 day) = CURRENT_DATE()
and hour(created_at) >= 15
) /*1*/
or (
date(created_at) = CURRENT_DATE()
and hour(created_at) <= 16
) /*2*/
)
And I get only orders made today - like only the 2nd condition was taken into account.
I prefer not to use created >= '2014-05-12 16:00:00' (I will not use this query, someone else will).

When you add an interval of 1 day to the date/time, you still keep the time component. Use date() for the first condition:
where status = 'new' and
((date(date_add(created_at, INTERVAL 1 day)) = CURRENT_DATE() and
hour(created_at) >= 15
) /*1*/ or
(date(created_at) = CURRENT_DATE() and
hour(created_at) <= 16
) /*2*/
)
And alternative method is:
where status = 'new' and
(created_at >= date_add(CURRENT_DATE(), interval 15-24 hour) and
created_at <= date_add(CURRENT_DATE(), interval 16 hour)
)
The advantage of this approach is that all functions are moved to CURRENT_DATE(). This would allow MYSQL to take advantage of an index on created_at.

Related

MySQL - How to find records for yesterday when timestamp is part of date

My MySQL table stores records with a date/time stamp. I am wanting to find records from the table that were created yesterday (as in have a creation date of yesterday - regardless of what the timestamp portion is)
Below is what a db record looks like:
I have tried the following select (and a few other variations, but am not getting the rows with yesterday's date.
SELECT m.meeting_id, m.member_id, m.org_id, m.title
FROM meeting m
WHERE m.create_dtm = DATE_SUB(CURDATE(), INTERVAL 1 DAY)
Not exactly sure how I need to structure the where clause to get meeting ids that occurred yesterday. Any help would be greatly appreciated.
A naive approach would truncate the creation timestamp to date, then compare:
where date(m.create_dtm) = current_date - interval 1 day
But it is far more efficient to use half-open interval directly against the timestamp:
where m.create_dtm >= current_date - interval 1 day and m.create_dtm < current_date
You can try next queries:
SELECT
m.meeting_id, m.member_id, m.org_id, m.title, m.create_dtm
FROM meeting m
-- here we convert datetime to date for each row
-- it can be expensive for big table
WHERE date(create_dtm) = DATE_SUB(CURDATE(), INTERVAL 1 DAY);
SELECT
m.meeting_id, m.member_id, m.org_id, m.title, m.create_dtm
FROM meeting m
-- here we calculate border values once and use them
WHERE create_dtm BETWEEN DATE_SUB(CURDATE(), INTERVAL 1 DAY) AND DATE_SUB(CURDATE(), INTERVAL 1 SECOND);
Here live fiddle: SQLize.online

How do I find all data from a table in a specific month

I am trying to retrieve all data from table in a specific month, my date format in the database table is 2016-06-19 I am need to find with the respect of a selected date, like if I select 2016-05-22
it will retrieve 2016-05-07 to 2016-06-06 interval values from the table.
And also to all the values in this month which is 05 month, I am using mysqli with PHP. I have tried using this query
SELECT * FROM t_tenancy_details WHERE
agreement_date >= DATE_FORMAT( CURRENT_DATE - INTERVAL 1 MONTH, '%Y/%m/01' )AND
agreement_date < DATE_FORMAT( CURRENT_DATE, '%Y/%m/01' )
This works fine for the running month, But problem is that if I select a previous month it does not work.
It's not very clear from the question as to what is needed. Based on the 2 requirements that I could understand:
Get everything surrounding the given date (i.e. +-15 days from the given date):
SELECT *
FROM t_tenancy_details
WHERE agreement_date >= DATE_SUB(#d, INTERVAL 15 DAY)
AND agreement_date <= DATE_ADD(#d, INTERVAL 15 DAY);
Get all the records where the month is same as the month in the given date:
SELECT *
FROM t_tenancy_details
WHERE MONTH(agreement_date) = MONTH(#d)
AND YEAR(agreement_date) = YEAR(#d);
where #d is the input date, in your case - CURRENT_DATE
Should be this
SELECT * FROM t_tenancy_details
WHERE (YEAR(t_tenancy_details) => YEAR(CURRENT_DATE - INTERVAL 1 MONTH)
AND MONTH(agreement_date) => MONTH(CURRENT_DATE - INTERVAL 1 MONTH))
AND (YEAR(t_tenancy_details) <= YEAR(CURRENT_DATE)
AND MONTH(agreement_date) <= MONTH(CURRENT_DATE))

mysql arithmetik operation (subtraction) last - first of the day(week, month)

i got a MySQL tbl, with some colums, where every 5 min. a new row is inserted with 3 values
1. Auto inc. curent Date Unix timestamp --> date
2. power consumption absolut --> wert01
3. Power Generation absolut --> wert02
To Show this Information in a Graph, for Exampl for weekly power consumption, i need to select the First and the last, which allready Works, but then have to Substract the last from the First and Show only tue result & the day of the werk.
SELECT
(SELECT wert01
FROM sml_splitt
WHERE date >= curdate() - INTERVAL DAYOFWEEK(curdate())+6 DAY
AND date < curdate() - INTERVAL DAYOFWEEK(curdate()) DAY
ORDER BY date DESC LIMIT 1) AS 'last',
(SELECT wert01
FROM sml_splitt
WHERE date >= curdate() - INTERVAL DAYOFWEEK(curdate())+6 DAY
AND date < curdate() - INTERVAL DAYOFWEEK(curdate()) DAY
ORDER BY date LIMIT 1) AS 'lirst
I am searching for some days to find a solution, but with no success.
Hopfuly, you could help me.
If you're happy with your query, then you can do the math by nesting it one more time like this: http://sqlfiddle.com/#!9/515ef/1
select t1.last, t1.first, t1.last - t1.first as result
from (
select (
select wert01
from sml_splitt
where dt >= curdate() - interval dayofweek(curdate()) + 6 day
and dt < curdate() - interval dayofweek(curdate()) day
order by dt desc limit 1
) as 'last',
(
select wert01
from sml_splitt
where dt >= curdate() - interval dayofweek(curdate()) + 6 day
and dt < curdate() - interval dayofweek(curdate()) day
order by dt limit 1
) as 'first'
) t1
;
If you really want to work with this data by week for reporting purposes, let me suggest a couple of views. The first will give you all of your distinct beginning of week dates:
create view v1 as
select date(dt) as week_begins
from sml_splitt
where dayofweek(dt) = 1
group by week_begins
The second view joins the first view with itself to give you a week beginning and week ending range:
create view v2 as
select t1.week_begins, coalesce(t2.week_begins,now()) as week_ends
from v1 t1
left join v1 t2
on t2.week_begins = t1.week_begins + interval 7 day
You can see the results here: http://sqlfiddle.com/#!9/a4d1b3/2. Notice that I'm using now() to get the current date and time if the week hasn't ended yet.
From there you can join your view with your original table and use min() and max() function with grouping to get the starting and ending 'wert' values and do any calculations on them that you like.
Here's an example: http://sqlfiddle.com/#!9/a4d1b3/6
select week_begins, week_ends,
min(wert01) as start_wert01,
max(wert01) as end_wert01,
max(wert01) - min(wert01) as power_consumed,
min(wert02) as start_wert02,
max(wert02) as end_wert02,
max(wert02) - min(wert02) as power_generated,
(max(wert02) - min(wert02)) - (max(wert01) - min(wert01)) as net_generated
from v2
inner join sml_splitt
on sml_splitt.dt >= v2.week_begins
and sml_splitt.dt < v2.week_ends
group by week_begins
I hope that helps.

SQL select subquery runs forever when passing MONTH to sub query

The purpose of this query:
contracts in the database have a start date, contract date and closing date.
When a contract goes pending, the contract date is set and the closing date is set to a around 40 days in the future. I need to run a query that gets the contracts that have a contract date in the past and closing date that has not been reached to find the number of pending contracts for that month. This query generate a report of pending contracts from the last full month and going back 12 months.
My thought is to get the last day of each month and count the number of contracts that have closing date > the last day of month and contract date <= last day of month
The following query executes in 51ms. the query returns rows for July
SELECT DATE_FORMAT(LAST_DAY(NOW() - INTERVAL 2 MONTH), '%Y-%m-%d 23:59:59') as lastDay,
count(*) as total FROM contracts
WHERE L_ClosingDate >= DATE_FORMAT(LAST_DAY(NOW() - INTERVAL 2 MONTH), '%Y-%m-%d 23:59:59')
AND L_ContractDate <= DATE_FORMAT(LAST_DAY(NOW() - INTERVAL 2 MONTH), '%Y-%m-%d 23:59:59')
Now I need to run the query to get rows grouped by month, so I altered the query to the following:
select MONTH(L_ClosingDate) as m, YEAR(L_ClosingDate) as y,
(SELECT count(*) FROM contracts WHERE L_ClosingDate >= DATE_FORMAT(LAST_DAY(CONCAT(y,'-',m,'-',LPAD(1,2,'00'))), '%Y-%m-%d 23:59:59')
AND L_ContractDate <= DATE_FORMAT(LAST_DAY(CONCAT(y,'-',m,'-',LPAD(1,2,'00'))), '%Y-%m-%d 23:59:59')
) as total
FROM contracts
WHERE L_ClosingDate > DATE_ADD(NOW(), INTERVAL -2 MONTH)
AND L_CLosingDate < DATE_ADD(NOW(), INTERVAL -1 MONTH)
GROUP BY YEAR(L_ClosingDate), MONTH(L_ClosingDate)
ORDER BY L_ClosingDate DESC
It executes forever...
I've tweaked it and found that the MONTH and YEAR 'm' and 'y' in the subquery is causing the problem. If I hardcode a date it executes as expected.
Expected output:
Month | Year | total
8 | 2015 | 74
7 | 2015 | 87
6 | 2015 | 45
I'm working on getting some sample data
Is there another way to perform the group by query?
How about this? (Assumes closing date is a datetime)
SELECT MONTH(L_ClosingDate) as m, YEAR(L_ClosingDate) as y
, count(*) as total
FROM contracts
WHERE L_ClosingDate >= LAST_DAY(CURDATE() - INTERVAL 3 MONTH) + 1 DAY
AND L_CLosingDate < LAST_DAY(CURDATE() - INTERVAL 1 MONTH) + INTERVAL 1 DAY
GROUP BY m, y
ORDER BY y DESC, m DESC
;
The easy way of solve this is create a months table, and that is easy to do because only take 1200 rows for whole century.
CREATE TABLE months (
month_id int,
beginDay date,
lastDay date
)
Then your query become much more simple. Just join and calculate between

Count of records for the last and current month unix timestamp

I need to make statistics page for billing with auto query. For example now is july and query must show count of record for the june and current count of records on current day(only july). Sort of:
"records for the last month - 85, for the current day - 32"
I have table customer and row create_time but it is in unix timestamp. Tried
SELECT COUNT(*) FROM customer WHERE create_time >=
UNIX_TIMESTAMP(DATE_SUB(now(), INTERVAL 1 MONTH))
but its absolutely not what i want.
I would appreciate for any help.
Try this:
SELECT *
FROM ( SELECT COUNT(*) AS total_previous_month
FROM customer
WHERE create_time >= concat(date_format(LAST_DAY(now() - interval 1 month),'%Y-%m-'),'01')
AND create_time < LAST_DAY(now() - interval 1 month )
) AS s1,
( SELECT COUNT(*) AS total_previous_month
FROM customer
WHERE create_time >= concat(extract(year from now()),'-',extract(month from now()),'-01')
AND create_time <= now()
) AS s2
You can do this by adding condition to the WHERE:
create_time >= UNIX_TIMESTAMP(DATE_SUB(CURDATE(), INTERVAL 1 month))
in PHP you can calculate the one month back date
$newDate = strtotime('-1 month');
and use this in query