Date ranking in Access SQL? - ms-access

I have a query pulling the last six months of data from a table which has a column, UseDates (so as of today in June, this table has dates for December 2011 through May 2012).
I wish to include a "rank" column that associates a 1 to all December dates, 2 to all January dates, etc -- up to 6 for the dates corresponding one month prior. If I were to open up this query a month from now, the 1 would then be associated with January, etc.
I hope this makes sense!
Example, if I ran the query right now
UseDate Rank
12/31/2011 1
1/12/2012 2
...
5/23/2012 6
Example, if I ran the query in August:
UseDate Rank
2/16/2012 1
3/17/2012 2
...
7/21/2012 6
Example, if I ran the query in March:
UseDate Rank
9/16/2011 1
10/17/2011 2
...
2/24/2012 6

SELECT
UseDates,
DateDiff("m", Date(), UseDates) + 7 AS [Rank]
FROM YourTable;

You can use month function for UseDates and subtract it from the result of now function. If it goes negative, just add 12. Also you may want to add 1 since you start with 1 and not 0. Apparently it should work for half a year date ranges. You'll get into trouble when you need to "rank" several years.

You can rank with a count.
SELECT
Table.ADate,
(SELECT Count(ADate)
FROM Table b
WHERE b.ADate<=Table.ADate) AS Expr1
FROM Table3;
You have to repeat any where statement in the subquery:
SELECT
Table.ADate,
(SELECT Count(ADate)
FROM Table b
WHERE b.ADate<=Table.ADate And Adate>#2012/02/01#) AS Expr1
FROM Table3
WHERE Adate>#2012/02/01#

Related

SQL group by days interval

I have a sample table here with the following columns and sample records. I want to be able to sum my column cases using with a specific date range (the helper column).
I want to get my results this way:
Sum all cases WHERE date range is in between 2022-03-23 - 2022-04-01 and so on.
date range
Sum of Cases
2022-03-23-2022-04-01
5 (sample result only)
2022-03-24-2022-04-02
9 (sample result only)
The logic of the date range is always n - n9 days.
I 've tried this type of query but it does not work, it there a way for me to get this without have to use a query to create another column?
SELECT Date,
sum([QUERY 1]) as "Reports 7 days prev",
sum ([QUERY 2]) as "Reports 7 days after"
FROM REPORTS
GROUP BY Date
Data:
Date
BuyerID
Cases
Helper (Date Range)
4/1/2022
20001
2
2022-03-23-2022-04-01
4/1/2022
20001
1
2022-03-23-2022-04-01
4/2/2022
20002
3
2022-03-24-2022-04-02
4/5/2022
20003
5
2022-03-27-2022-04-05
4/7/2022
20004
6
2022-03-29-2022-04-07
4/7/2022
20005
9
2022-03-29-2022-04-07
Are you looking to get total cases for last X number of days? What does your initial data look like?
you can try something like:
Step 1: You aggregate all the cases for each date.
WITH CASES_AGG_BY_DATE AS
(
SELECT Date,
SUM(Cases) AS Total_Cases
FROM REPORTS
GROUP BY Date
),
Step 2: you aggregate the last 7 days rolling cases sum for each date
LAST_7_DAY_AGG AS
(
SELECT Date, SUM(Total_Cases) OVER(ORDER BY Date ASC ROWS BETWEEN 7 PRECEDING AND CURRENT ROW) AS sum_of_cases,
LAG(Date, 7) AS 7th_day
FROM CASES_AGG_BY_DATE
)
Step 3: create final output and concatenate date and 7th day before that
SELECT Date, CONCAT(Date, "-", 7th_day), sum_of_cases
FROM LAST_7_DAY_AGG;

How to get date from week number and day in sql?

I have both the week number and their corresponding day of week(i.e. mon,tue,wed,.....) stored in tables.
The following code is supposed to return week number from date but I'm unable to turn this around
select WEEKOFYEAR(CURDATE())
My table:
RecordID|Record|WeekID|DayofWeek
--------------------------------
1 |text1 |43 |mon
2 |text2 |43 |tue
3 |text3 |44 |wed
Desired output:
RecordID|Record|Date
--------------------------------
1 |text1 |2019/10/30
2 |text2 |2019/10/31
3 |text3 |2019/11/01
I want to retrieve the date from them(assuming current year). Is it possible in sql or can it be done only on server side?
*Dates just for representation
This following sample script might help you. Hope all necessary values are available in your database and you have pass them to the function accordingly-
SELECT STR_TO_DATE('2013 10 Tuesday', '%X %V %W');
--2013 is the year value
--10 is the week number
--Tuesday is the day name
If you have all three values available in your table and run the STR_TO_DATE function providing appropriate values - this will return you a date like - "2013-03-12".
You can check the below script-
SELECT
STR_TO_DATE(concat('2019',' ', WeekID,' ', DayofWeek), '%X %V %W')
FROM (
SELECT 1 RecordID, 'text1' Record, 43 WeekID,'mon' DayofWeek UNION ALL
SELECT 2,'text2',43,'tue' UNION ALL
SELECT 3,'text3',44,'wed'
)A;
Your final query should be as below-
SELECT
STR_TO_DATE(concat('2019',' ', WeekID,' ', DayofWeek), '%X %V %W')
FROM your_table_name A;
Note: Year 2019 is fixed as this value is not available in your table. If available, you can also use that column dynamically as other columns are used.
Your question isn't completely clear.
I guess you have the columns
year with values like 2001
WeekID with values like 36
DayOfWeek with values like tue.
Then, you can use an expression like this to get the DATE value. MySQL has date format strings for week and weekday.
SELECT STR_TO_DATE (CONCAT(year, '/', week, '/', weekday), '%Y/%v/%a')
Here's a fiddle. https://www.db-fiddle.com/f/iGrnkM5WgWTVPxuqxfPxdK/0
But beware, the computation of week number is a business rule subject to local and international standards. Be sure to test with dates in the first few days of several different calendar years to make sure you understand your situation.
You can read about the choices for week computation here. You use WEEKOFYEAR() to retrieve the week number; that corresponds to the %v format specifier.
You cant get the date from just week number and day of week, you would need the year too.

How to filter Records based on the condition from Two Columns that are dependent

I have a Table in the Database with below columns :
Month
Year
Name
xyz
abc
The table would have multiple Records but there is a unique constraint on the combination of Month, Year and Name.
The table would have data Like below :
Month Year Name
1) 1 2016 test1
2) 2 2016 test2
3) 3 2016 test3
4) 1 2017 test4
5) 2 2017 test5
Now I want records that are Greater than or Equal to Month 3 and Greater than equal to Year 2016.
So the output Should be Like Below:
Month Year Name
1) 3 2016 test3
2) 1 2017 test4
3) 2 2017 test5
How can this be accomplished. I am not getting any hint on how this can be done.I was adding a where clause with month>=3 and year>=2016 but it does not return any record and I think is correct as I am applying And condition on two expressions.
To produce the result as you have described in your second table, I would write this query:
select [Month], [Year], [Name]
from Table -- your table name
where year > 2016 or ( year = 2016 and month >= 3) -- don't forget the parentheses.
What I can understand from your result table, the query described in words will be:
Give me all the records where the year is greater than 2017 (in this case month doesn't matter, give me all the months) or if the year is 2016, give me all months greater than or equal to 3 (March included and onward). Don't give me any records where the year is smaller than 2016.
If this is correct, then the query I posted above gives the right result.
If you want to get all records starting on or after '2016-03-01' then one way would be to build your [year] and [month] back into a date datatype.
select *
from t
where convert(date,convert(varchar(10),([year]*10000)+([month]*100)+1)) >= '20160301'
or in sql server 2012 +
select *
from t
where datefromparts([year],[month],1) >= '20160301'
Your question is not clear. From the explanation you want "and" condition but in the output result it should be "or". For ex month >= 3 or year>=2016. This is your output saying.

How can I get the month that is not yet updated in SQL by inserting another row on every update?

I have a table that contains records of different transaction that is needed to be updated monthly. Once the record for a specific month has been successfully updated, it will insert a new record to that table to indicate that it is already updated. Let's take this example.
**date_of_transaction** **type**
2015-04-21 1 //A deposit record
2015-04-24 2 //A withdrawal record
2015-04-29 1
2015-04-30 2
2015-04-30 3 //3, means an update record
2015-05-14 1
2015-05-22 1
2015-05-27 2
2015-05-30 2
2015-06-09 1
2015-06-12 2
2015-06-17 2
2015-06-19 2
Let's suppose that the day today is July 23, 2015. I can only get the data one month lower than the current month, so only the data that I can get are june and downwards records.
As you can see, there is an update performed in the month of April because of the '3' in the type attribute, but in the month of May and June, there are no updates occurred, how can I get the month that is not yet updated?
This will return you months, which has no type=3 rows
SELECT MONTH([trans-date]) FROM [table] GROUP BY MONTH([trans-date]) HAVING MAX([trans-type])<3
Note: this will not work if 3 is not max value in the column
My approach would be to find all the months first, then find the months whose records were updated. Then select only those months from all months whose records werent updated (A set minus operation).
Mysql query would be something like this
select extract(MONTH,data_of_transaction) from your_table_name where month not in (select extract(MONTH,data_of_transaction) from table where type=3);
You can try this;
select *
from tbl
where date_of_transaction < 'July 23, 2015'
and
date_format(date_of_transaction, '%M-%Y') in (
select
date_format(date_of_transaction, '%M-%Y')
from tbl
group by date_format(date_of_transaction, '%M-%Y')
having max(type) != 3
)
date_format(date_of_transaction, '%M-%Y') will take month-year in consideration and filter the data having type = 3.

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