SQL week number for the whole table - sql

How to create a new column which calculates week number but for the whole table ignoring year?
Desired output is as follows:
Appreciate any help :)

You can do this by calculating 1st day of week of oldest row, and then calculate day diff of 1st day of week of current row and coldest row, after that, divide it by 7 days plus 1 will give you the desired week number across the full table.
Assuming you are using MySQL and the first day of the week is Sunday:
WITH min_week_start AS (
SELECT
SUBDATE(MIN(record_date), dayofweek(MIN(record_date)) - 1) as week_start_date
FROM
record_table
),
record_week_start AS (
SELECT
record_date,
SUBDATE(record_date, dayofweek(record_date) - 1) as week_start_date
FROM
record_table
)
SELECT
record_week_start.record_date,
DATEDIFF(record_week_start.week_start_date, min_week_start.week_start_date) / 7 + 1 as week_num
FROM
record_week_start
CROSS JOIN
min_week_start

Related

Write a SQL Query in Google Big Query which pulls all values from last week, all values from 2 weeks ago, and calculate percent change between them

I'm trying to query a table comparing order numbers from last week (Sunday to Saturday) vs 2 weeks ago, and calculate percent change between the two. My thought process so far has been to group my date column by week, then use a lag function to pull last week and the previous week in to the same row. From there use basic arithmetic functions to calculate percent change. In practice, I haven't been able to get a working query, but I picture the table to look as follows:
Week
Orders
Orders - Previous Week
% Change
2023-02-05
5
10
-0.5
2023-01-29
10
2
+5.0
2023-01-29
2
Important to note that the days in last week should not change regardless of what day it is today (i.e not use today -7 days to calculate last week, and -14 days to calculate 2 weeks ago)
My query so far:
SELECT
min(date) as date,
orders,
coalesce(lag(order) over (order by (date), 0)) as Orders - Previous Week
FROM `table`
WHERE date BETWEEN '2023-01-01' AND current_date()
group by date_trunc(date, WEEK)
ORDER BY date desc
I realize I'm not using coalesce and my lag function correctly, but a bit lost on how to correct it
To calculate the percent change, you can use the following query:
sql
Copy code
SELECT
min(date) as Week,
sum(orders) as Orders,
coalesce(sum(lag(orders) over (order by date_trunc(date, WEEK))), 0) as "Orders - Previous Week",
(sum(orders) - coalesce(sum(lag(orders) over (order by date_trunc(date, WEEK))), 0)) / coalesce(sum(lag(orders) over (order by date_trunc(date, WEEK))), 0) as "% Change"
FROM `table`
WHERE date BETWEEN '2023-01-01' AND current_date()
group by date_trunc(date, WEEK)
ORDER BY Week desc
In this query, the sum function is used to aggregate the orders by week. The coalesce function is used to handle the case where there is no previous week data, and default to 0. The percent change calculation uses the same formula you described.

SQL moving average by weekday with moving range for last 4 weeks, excluding current week

I'm trying to calculate 7 day moving average by weekday, for last 4 weeks but not including the current week. The code below calculates the average however that includes the current week's data. How can I exclude the current week and only calculate last 4 Sundays, Mondays, Tuesdays, etc. Please note, the average will differ by day. For example, each Sunday will have a different average based on the last 4 weeks.
Attached is the sample data and desired results Data example
Select a.Date, a.WeekDay,
avg(a.count) Over(partition by a.WeekDay order by a.Date rows between 3 preceding and current row) as rolling_avg
from
(Select Date, WeekDay, Count from Sales) a
Where a.Date >= current_date- 7*7
You almost have it, change the way to use following ROWS. You need to use FOLLOWING 1 to use starting next row and 4 as the limit. I also changed the order by date desc that, way the next row is the previous week.
Select
a.Date_V,
a.WeekDay,
--AVG(CAST(a.count_v AS DECIMAL(8,2))) OVER /*cast optional*/
AVG(a.count_v) Over
(partition by a.WeekDay order by a.date_v desc
ROWS BETWEEN 1 FOLLOWING AND 4 FOLLOWING) as rolling_avg
FROM
(Select Date_V, WeekDay, Count_v from historic_data) a
Where a.Date_v >= GETDATE()- 7*7
ORDER BY a.date_v desc
I created following SQL Fiddle for testing if someone wants to play with it.

In Bigquery SQL: How to fetch previous week, specified week and next week data?

Scenario: From bigquery, have to fetch the specified date's week data + its previous week data + its next future week data. Week starts is Wednesday.
Tried Query:
Select * from table
and extract(week(wednesday) from Calendar_Day) >= (extract(week(wednesday) from PARSE_DATE('%d/%m/%Y','21/10/2020')) - 1)
and extract(week(wednesday) from Calendar_Day) >= (extract(week(wednesday) from PARSE_DATE('%d/%m/%Y','21/10/2020') ))
and extract(week(wednesday) from Calendar_Day) <= (extract(week(wednesday) from PARSE_DATE('%d/%m/%Y','21/10/2020')) + 1)
But this is not working for me.
Need help in resolving this. Thanks in Advance!
EXTRACT the week as the code already does. and the year as the weeks repeat every year.
GROUP BY the week and year. At this point I find it handy to make a STRUCT from the remaining fields as it simplifies the remaining code.
make another query that uses the query which did the GROUP BY, I used a WITH. In this last query, LEAD and LAG the data with a WINDOW by week.
Here's an example from a public dataset.
WITH
data_by_week AS (
SELECT
EXTRACT(year FROM date) AS year,
EXTRACT(week(wednesday) FROM date) AS week,
struct(
SUM(new_tested) as total_new_tested,
sum(new_recovered) as total_new_recovered
) as week_data
FROM
`bigquery-public-data.covid19_open_data.covid19_open_data`
GROUP BY
year,
week )
SELECT
year,
week,
LAG(week_data) OVER window_by_week AS previous_week,
week_data AS current_week,
LEAD(week_data) OVER window_by_week AS following_week
FROM
data_by_week
WINDOW
window_by_week AS ( ORDER BY year, week)
ORDER BY
year,
week

Select next value where it equals another value

I have a table of the fiscal year for 100 years. i.e.
I am wanting to do add a column which shows the fiscal year that each week_ending_date belongs to. So in the table above week number 1, and week_ending_date 2013-10-05 would belong to fiscal year ending 2014.
In short I simply want each value in the added column to be the year part of week_ending_date where the next week_number is 52.
Here would be the pseudo code of what I am trying to achieve.
SELECT
Week_Ending_Date,
(SELECT NEXT VALUE FOR Week_Ending_Date (***but as only year***) FROM Fiscal_Calendar WHERE FC.Week_Number = 52)
FROM Fiscal_Calendar AS FC
JOIN Shipped_Container AS SC
ON SC.Fiscal_Week_Ending = FC.Week_Ending_Date
Bare in mind this has 100 years in the table and so I can't select the last value and makes using WHERE difficult (for me).
One way you can do this is by subtracting 7 * week number, taking the year and adding 1:
select 1 + year(dateadd(day, -7 * week_number, week_ending_date))

How to calculate Last Week of Month by WeekNO and Year in SQL

I want to calculate Last Week Number of Month in SQL. I am having Week Number and Year.
Eg. If I pass WeekNo=51 , Year=2008 , than function should return LastWeekofMonth= 52.
I want to calculate Week number using below standards.
According to ISO 8601:1988 that is used in Sweden the first week of the year is the first week that has at least four days within the new year.
So if your week starts on a Monday the first Thursday any year is within the first week. You can DateAdd or DateDiff from that.
Please Help me..........
Thanks in advance.
SELECT WEEK(LAST_DAY(STR_TO_DATE('2008-51-Mon', '%x-%v-%a')));
Should do the trick for getting the last week number of month with MySQL :
I first convert to a date, then I get the last day of the month (here: 2008-12-31), then I compute the week of the last day of the month (52).
It should be easy to turn it into a function.
Hope this helps.
This is fairly straightforward if you use a calendar table. The month you need is given by this query.
select iso_year, month_of_year
from calendar c
where iso_year = 2008 and iso_week = 51
group by iso_year, month_of_year
--
iso_year month_of_year
2008 12
So you can use that result in a join on the calendar table, like this.
select max(c.iso_week) as last_week_of_month
from calendar c
inner join
(select iso_year, month_of_year
from calendar c
where iso_year = 2008 and iso_week = 51
group by iso_year, month_of_year) m
on m.iso_year = c.iso_year and m.month_of_year = c.month_of_year;
--
last_week_of_month
52
Here's one example of a calendar table, but it's pretty thin on CHECK constraints.
If you're using SQL Server, you can perform a calculation by using a master table, without creating a calendar table. This fellow gives you a very good explanation, which I recommend that you read. His SQL for calculating the first and last Sundays of each month can be adapted for your use:
declare #year int
set #year =2011
select min(dates) as first_sunday,max(dates) as last_sunday from
(
select dateadd(day,number-1,DATEADD(year,#year-1900,0))
as dates from master..spt_values
where type='p' and number between 1 and
DATEDIFF(day,DATEADD(year,#year-1900,0),DATEADD(year,#year-1900+1,0))
) as t
where DATENAME(weekday,dates)='sunday'
group by DATEADD(month,datediff(month,0,dates),0)
Edit: Once you have the date of the Thursday, you can get the week number from that date like this:
DECLARE #Dt datetime
SELECT #Dt='02-21-2008'
SELECT DATEPART( wk, #Dt)