Retrieve ALL row data from TWO different months in SAME table? - mysql

Re-do Times 2 for clarity
For simplicity and clarity, the data I am aggregating is in a database I will refer to as "BaseA".
Normally, when comparing Month over month data, I can use the following query:
select date_trunc('month',hour) as date,
sum(a) as total_a,
sum(b) as available_b,
sum(c) as c,
sum(d) as net_d
from BaseA where id=12345 and hour >='2022-01-01'
group by date order by date desc
Instead of looking back and collecting ALL months from 2021-2022 for the duration I wish to view, I want to collect ONLY two months of data, those being the following:
October 2021
vs.
April 2022
I'd like the data to be visualized in the Month over month format, like so:
example
However, I would like to:
Select all BaseA columns (aka, select *)
Only include Two rows: April 2022 & October 2021
So, should come out like so:
example 2
This query is what Im trying to do (in word form since I can't write it)
Select *
from BaseA
where date
is in
April 2022
&
October 2022
The result of the above should result in 2 rows of data (one for each month referenced)
Is there a place in the below query where DISTINCT would make that actualized?
select * from BaseA
where id=12345 and
(
(month(month) = '04' and year(month) = '2022')
OR
(month(month) = '10' and year(month) = '2021')
)
--DISTINCT go where?
Appreciate the help!

To get data for the two months try something like this:
select * from BaseA
where _id=12345 and
(
(month(month) = '04' and year(month) = '2022')
OR
(month(month) = '10' and year(month) = '2021')
)
I have no idea what you mean by "return data consolidated (grouped) by month (so multiple lines occur per month)". Can you provide dummy data that illustrates the data that you have and the result that you want to achieve?

Related

MySQL Date in where clause

I have a table which contains date (Field Type: Date and Date Format: %Y-%m-%d) as a field. I need to select all the rows from the table for all the years whose date is not between Dec 3rd and Dec 24th.
The table contains month and day as a separate fields.
The result can be obtained by using the following query:
select * from mytable where date not in (select date from mytable where month=12 and day between 3 and 24);
But i m trying to get the result in a single query like the below one but it gave empty rows:
select * from mytable where date not between '%Y-12-03' and '%Y-12-24';
Can it be done in a single query like the above one?
SELECT *
FROM mytable
WHERE MONTH(`date`) <> 12
OR DAY(`date`) NOT BETWEEN 3 AND 24
;
This will give you every row that meets the requirements. I'm sure someone has a faster way of doing this, since this will ignore all indexes and will likely be slow on a large dataset, but it does work and return the data you require, so if no-one can suggest an improvement this will answer your question.

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

In SQL date function for before 2 months

I mentioned database table structure below,
name, expired_date, address, payment_date
----------------------
name1, 2013/06/02, address1,2013/07/23
name2, 2013/06/02, address2,2013/07/23
name3, 2013/04/02, address3,2013/07/23
name4, 2013/05/02, address4,2013/07/23
name5, 2013/06/02, address5,2013/07/24
...
name6, 2013/06/02, address6,.....
In this table I update date in yyyy/mm/dd format . current month is April but I need after two records only.
For example I need 06 month records only.
I need SQL query for this.
Assuming you want to query by expired_date:
Following query gets records after two months from current date:
SELECT * FROM tableName where expired_date>=DATE_ADD(CURDATE(), INTERVAL 1 MONTH)
If you specifically want records for June:
SELECT * FROM tableName where expired_date>='2013-06-01' AND expired_date<'2013-07-01'
Try it.
Select [fields] from [yourtable] where Month([yourDateField]) = [Value, ex: for June : 6]
Implement
I am assuming you want to check expired_date
Select * from Table1 where Month(expired_date) = 6
if you want to check year also then, assuming year is 2013.
Select * from Table1 where Month(expired_date) = 6 and Year(expired_date) = 2013

MySQl Query optimization

I have a table with a list of tasks. Each task has a datetime field called "completedTime". Basically everytime a task is marked completed that field gets updated with the correct time.
Now I need to do a graph (using jQuery) for this result where the x axis is the months of the year (jan-dec) and the y axis is a number.
What is the sql query can I use so it would spit out 12 columns (Jan-Dec) with a number in each depending on how many tasks have a completedTime in that month.
I don't want to run the query below 12 times or each month.
SELECT * FROM `tasks` WHERE month(completedTime) between '02' and '03';
Any ideas?
If I understand correctly, your want it to return 12 rows (one for each month) with a count of the number of tasks.
If that is correct, then something like this should work. I added the year, which could be parametrized.
SELECT Count(*)
FROM Tasks
WHERE Year = 2011
GROUP BY Month(completedTime);
Revised with name for Month
SELECT Count(*) as total,
DateName(month, DateAdd(month, Month(completedTime), 0 ) - 1 ) as Month
FROM tasks
WHERE year(completedTime) = '2011'
GROUP BY Month(completedTime)

Get the last twelve months worth of data from a database

I'm trying to work with a database of unemployment figures from the department of labor statistics' data (available at ftp://ftp.bls.gov/pub/time.series/la/)
I need to get the last 12 months of data for any given state, which is trickier then just selecting all data from the last year as they don't always have the last few months of data in yet (right now, the last month's worth of data is November 2010).
I know which record is the newest, and the date fields I have in the database to work with are:
period_name (month name)
year
period (M01, M02, etc for January, February)
My current SQL, which pulls data from a bunch of JOINed tables, is:
USE unemploymentdata;
SELECT DISTINCT series.series_id, period_name, year, value, series.area_code,
footnote_codes, period_name, measure_text, area_text, area_type_text
FROM state_overview
LEFT JOIN series ON state_overview.series_id=series.series_id
LEFT JOIN footnote ON state_overview.footnote_codes = footnote.footnote_code
LEFT JOIN period ON state_overview.period = period.period
LEFT JOIN measure ON series.measure_code = measure.measure_code
LEFT JOIN area ON series.area_code=area.area_code
LEFT JOIN area_type ON area.area_type_code=area_type.area_type_code
WHERE area_text = 'State Name' AND year > 2009
ORDER BY state_overview.period, measure_text;
Any idea?
Since you have textual values to work with for month and year, you'll need to convert them to MySQL-formatted DATE values and can then let MySQL calculate the last year interval like so:
SELECT ... WHERE STR_TO_DATE(CONCAT(period_name,' 1 ',year),'%M %d %Y') >= DATE_SUB(STR_TO_DATE(CONCAT(most_recent_period_name,' 1 ',most_recent_year),'%M %d %Y'), INTERVAL 1 YEAR) ...;
The CONCAT() function is just building a string like "Month 1 YYYY", and the STR_TO_DATE() function is taking that string and a formatting string to tell it how to parse it, and converting it into a DATE.
Note: This query probably sucks index-wise but it should work. : )
I think a few changes to WHERE clause should do it, but for effeciency/simplcity you should also add MAX(year) to the SELECT section.
SELECT ...... MAX(year) as max_year .....
WHERE area_text = 'State Name'
AND year >= max_year - 1
AND period >= (SELECT MAX(period) WHERE year = max_year)
ORDER BY state_overview.period, measure_text;
You can store the year and month as a date, even though you don't have the day information. Just use the first of each month.
{2009, 'M1'} => 2009-01-01
{2009, 'M2'} => 2009-02-01
{2009, 'M3'} => 2009-03-01
This makes date arithmetic much easier than dealing with substrings of (potentially dirty) data. Plus (and this is big), you can index the data much more effective. As a bonus, you can now extract a lot of extra goodies using DATE_FORMAT such as month names, nr of days in month etc.
Does all states have data for all months, and is the data updated at the same time? The answer to that question dictates what query strategy you should use.
The best way is to take the strtotime ($a) of correct 1 year ago and then, when fetching the value from database then find the strtotime ($b) of the date in each result. Now
if($b < $a){
continue;
}
else {
//do something.
}