check if in existing result set all days within month are present - mysql

How can I check if in my result set (which is formed by query shown below at the end) for every month exists every day? For example in below result set:
Date_List
08/01/2016
08/02/2016
08/03/2016
08/04/2016
08/05/2016
08/06/2016
08/07/2016
08/08/2016
08/09/2016
08/10/2016
08/11/2016
08/12/2016
08/13/2016
08/14/2016
08/15/2016
08/16/2016
08/17/2016
08/18/2016
08/19/2016
08/20/2016
08/21/2016
08/22/2016
08/23/2016
08/24/2016
08/25/2016
08/26/2016
08/27/2016
08/28/2016
08/29/2016
08/30/2016
08/31/2016
We can see that August 2016 has all days available. I want to return only such months (with all days available) with a year part of course. In this case it would be 08/16 (MM/YYYY) to return. Thus if any day for any month is missing - I do not want to return such month.
Here is the query I use to form result set:
SELECT d.`Date_List` FROM staging_area.`g360_dates_ca` d
LEFT JOIN dm_research_development.g360_pro_saas_availability a
ON d.`Date_List` = a.`DATE_OCCURRED_DATE` AND a.`IS_OUTAGE` = 'YES'
WHERE a.`DATE_OCCURRED_DATE` IS NULL AND STR_TO_DATE(d.`Date_List`,'%m/%d/%Y') <= NOW();
g360_dates_ca table contains all dates starting 01-01-2013 till 01-01-2018.
g360_pro_saas_availability - is my incidents table with details.

Related

SQL query to find if a date falls between two others

I have a table that I'd like to run a SQL query on. I want to find all the customers that have a status active and have their interval_type set to interval. That part is fine, it's the next part I'm struggling with.
I want to find any orders that are to be processed between between Dec 1st 2019 and Dec 6th 2019.
The difficulty is that in my table I have the columns "interval", this can be a number between 15-75 days (and is converted to seconds) and when their order was last processed (also a unix timestamp) in the column called "last_processed".
If the "interval" (in seconds) is added to the "last_processed" (a date), does that new date fall between the 1st and 6th of Dec. How can I do that?
SELECT *
FROM subscriptions
WHERE
status = 'active' AND
interval_type = 'interval' AND
`interval` BETWEEN 1575158400 AND 1575676740;
Here's what the data looks like in my table:
You can do it this way
SELECT *,
FROM_UNIXTIME(last_processed+`interval`)
FROM subscriptions
WHERE status = 'active' AND
interval_type = 'interval'
AND (last_processed + `interval`) BETWEEN UNIX_TIMESTAMP('2019-12-01 00:00:00')
AND UNIX_TIMESTAMP('2019-12-06 23:59:59');
DBfiddle Example
Next time please use text instead or directly a dbfiddle example, than you can get an answer much earlier. That's why i posted the link for a minimal example.

MySQL - get data for time before some quarter AND year

I need to get MySQL results for users records with 'registered' date that happens BEFORE some quarter for some year.
For example to get data (users count, registered before Q3 2018) I do this request:
SELECT count(userid) AS value
FROM users
WHERE QUARTER(registered) <= "3" && YEAR(registered) <= "2018"
However this request give me not expected results (value much lower that it should be, looks like I get results only for Q3 for 2018 year, and without values for previous years with any quarters). If I remove quarter and check just data before Year - this works fine and show correct results for every year that I use.
Why this happens and how to correctly get value with Quarter?
You can use the following solution:
SELECT COUNT(userid) AS value
FROM users
WHERE YEAR(registered) < 2018 OR (
YEAR(registered) = 2018 AND QUARTER(registered) <= 3
)
With your current SELECT you get only all users which registered on third quarter or ealier on every year (2018 and earlier). But you can count all users of the years before 2018 (the quarter doesn't matter in this case) and all users of the current year but in the specified quarter or ealier.

Get value difference between two dates in MySQL

I have a following table structure:
page_id view_count date
1 30 2018-08-30
1 33 2018-08-31
1 1 2018-09-01
1 5 2018-09-02
...
View count is reset on 1st of every month, and it's current value is stored on a daily basis, so on 31st of August it was increased by 3 (because 33-30).
What I need to do is to retrieve the view count (difference) between two dates through SQL query. To retrieve view count between two dates in same month would be simple, by just subtracting bigger date with the lower date, but retrieving between two dates that are in different months is what's not sure to me how to achieve. If I wanted to retrieve data between 2018-08-13 and 2018-09-13 I would have to get difference between 2018-08-31 and 2018-08-13, and add it to the value of 2018-09-13.
Also, I would like to do it for all page_id at once, between the same dates if possible within a single query.
assuming that the counter is unique per page and that the page_id counter is inserted daily into the table, I think that such a solution would work
The dates are based on the example,
and should be replaced by the relevant parameters
SELECT
v1.view_count + eom.view_count - v2.view_count
FROM
view_counts v1
INNER JOIN view_counts v2 ON v2.page_id = v1.page_id AND v2.`date` = '2018-08-13'
INNER JOIN view_counts eom ON v2.page_id = v.page_id AND eom.`date` = LAST_DAY(DATE_ADD(v.`date`, INTERVAL -1 MONTH))
WHERE
`date` = '2018-09-13'

Get stats for each day in a month without ignoring days with no data

I want to get stats for each day in a given month. However, if a day has no rows in the table, it doesn't show up in the results. How can I include days with no data, and show all days until the current date?
This is the query I have now:
SELECT DATE_FORMAT(FROM_UNIXTIME(timestamp), '%d'), COUNT(*)
FROM data
WHERE EXTRACT(MONTH FROM FROM_UNIXTIME(timestamp)) = 6
GROUP BY EXTRACT(DAY FROM FROM_UNIXTIME(timestamp))
So if I have
Row 1 | 01-06
Row 2 | 02-06
Row 3 | 03-06
Row 4 | 05-06
Row 5 | 05-06
(i changed timestamp values to a day/month date just to explain)
It should output
01 | 1
02 | 1
03 | 1
04 | 0
05 | 2
06 | 0
...Instead of ignoring day 4 and today (day 6).
You will need a calendar table to do something in the form
SELECT `date`, count(*)
FROM Input_Calendar c
LEFT JOIN Data d on c.date=d.date
GROUP BY `date`
I keep a full copy of a calendar table in my database and used a WHILE loop to fill it but you can populate one on the fly for use based on the different solutions out there like http://crazycoders.net/2012/03/using-a-calendar-table-in-mysql/
In MySQL, you can use MySQL variables (act like in-line programming values). You set and can manipulate as needed.
select
dayofmonth( DynamicCalendar.CalendarDay ) as `Day`,
count(*) as Entries
from
( select
#startDate := date_add( #startDate, interval 1 day ) CalendarDay
from
( select #startDate := '2013-05-31' ) sqlvars,
AnyTableThatHasAsManyDaysYouExpectToReport
limit
6 ) DynamicCalendar
LEFT JOIN Input_Calendar c
on DynamicCalendar.CalendarDay = date( from_unixtime( c.date ))
group by
DynamicCalendar.CalendarDay
In the above sample, the inner query can join against as the name implies "Any Table" in your database that has at least X number of records you are trying to generate for... in this case, you are dealing with only the current month of June and only need 6 records worth... But if you wanted to do an entire year, just make sure the "Any Table" has 365 records(or more).
The inner query will start by setting the "#startDate" to the day BEFORE June 1st (May 31). Then, by just having the other table, will result in every record joined to this variable (creates a simulated for/next loop) via a limit of 6 records (days you are generating the report for). So now, as the records are being queried, the Start Date keeps adding 1 day... first record results in June 1st, next record June 2nd, etc.
So now, you have a simulated calendar with 6 records dated from June 1 to June 6. Take that and join to your "data" table and you are already qualifying your dates via the join and get only those dates of activity. I'm joining on the DATE() of the from unix time since you care about anything that happend on June 1, and June 1 # 12:00:00AM is different than June 1 # 8:45am, so matching on the date only portion, they should remain in proper grouping.
You could expand this answer by changing the inner '2013-05-31' to some MySQL Date function to get the last day of the prior month, and the limit based on whatever day in the current month you are doing so these are not hard-coded.
Create a Time dimension. This is a standard OLAP reporting trick. You don't need a cube in order to do OLAP tricks, though. Simply find a script on the internet to generate a Calendar table and join to that table.
Also, I think your query is missing a WHERE clause.
Other useful tricks include creating a "Tally" table that is a list of numbers from 1 to N where N is usually the max of the bigint on your database management system.
No code provided here, as I am not a MySQL guru.
Pseudo-code is:
Select * from Data left join TimeDimension on data.date = timedimension.date

SQL Statement Database

I have a Mysql Table that holds dates that are booked (for certain holiday properties).
Example...
Table "listing_availability"
Rows...
availability_date (this shows the date format 2013-04-20 etc)
availability_bookable (This can be yes/no. "Yes" = the booking changeover day and it is "available". "No" means the property is booked for those dates)
All the other dates in the year (apart from the ones with "No") are available to be booked. These dates are not in the database, only the booked dates.
My question is...
I have to make a SQL Statement that first calls the Get Date Function (not sure if this is correct terminology)
Then removes the dates from "availability_date" WHERE "availability_bookable" = "No"
This will give me the dates that are available for bookings, for the year, for a property.
Can anyone help?
Regards M
Seems like you've almost written the query.
SELECT availability_date FROM listing_availability
WHERE availability_bookable <> 'NO'
AND availability_date >= CURDATE()
AND YEAR(CURDATE()) = YEAR(availability_date)
I think I understand, and you'll obviously confirm. Your "availability_booking" has some records in it, but not every single day of the year, only those that may have had something, and not all are committed, some could have yes, some no.
So, you want to simulate All dates within a given date range... Say April 1 - July 1 as someone is looking to book a party within that time period. Instead of pre-filling your production table, you can't say that April 27th is open and available... since no such record exists.
To SIMULATE a calendar of days for a date range, you can do it using MySQL variables and join to "any" table in your database provided it has enough records to SIMULATE the date range you want...
select
#myDate := DATE_ADD( #myDate, INTERVAL 1 DAY ) as DatesForAvailabilityCheck
from
( select #myDate := '2013-03-31' ) as SQLVars,
AnyTableThatHasEnoughRows
limit
120;
This will just give you a list of dates starting with April 1, 2013 (the original #myDate is 1 day before the start date since the field selection adds 1 day to it to get to April 1, then continues... for a limit of 120 days (or whatever you are looking for range based -- 30days, 60, 90, 22, whatever). The "AnyTableThatHasEnoughRows" could actually be your "availability_booking" table, but we are just using it as a table with rows, no join or where condition, just enough to get ... 120 records.
Now, we can use this to join to whatever table you want and apply your condition. You just created a full calendar of days to compare against. Your final query may be different, but this should get it most of the way for you.
select
JustDates.DatesForAvailabilityCheck,
from
( select
#myDate := DATE_ADD( #myDate, INTERVAL 1 DAY ) as DatesForAvailabilityCheck
from
( select #myDate := '2013-03-31' ) as SQLVars,
listing_availability
limit
120 ) JustDates
LEFT JOIN availability_bookable
on JustDates.DatesForAvailabilityCheck = availability_bookable.availability_date
where
availability_bookable.availability_date IS NULL
OR availability_bookable.availability_bookable = "Yes"
So the above uses the sample calendar and looks to the availability. If no such matching date exists (via the IS NULL), then you want it meaning there is no conflict. However, if there IS a record in the table, you only want those where YES, you CAN book it, the entry on file might not be committed and CAN be in your result query of available dates.