Retrieve the Financial Year data - sql

How to access the data from MSSQL table
User will give only month(3) and financial year(2013-14), how can I retrieve the progress up to last month (previous month) and up to month (this month) while data has been inserted from jun-2013 to march-2014
I have tried but I have given like month 3 and financial year 2013-14 but its calculate only two month data while it should be calculate Apr-2013 to Mar-2014 data
My table structure is like
+--------+-------+------+---------+
| amount | month | year | finyear |
+--------+-------+------+---------+
| 12456 | 2 | 2013 | 2013-14 |
+--------+-------+------+---------+
thanks

Something like this should do it:
SELECT SUM(a.amount) + SUM(b.amount)
FROM table a
INNER JOIN table b ON b.year = a.year - 1
WHERE a.finyear = '2013 - 14'
AND a.month <= 3
AND b.month > 3
Although your data structure and example data is pretty confusing..

Related

SQL - BigQuery - How do I fill in dates from a calendar table?

My goal is to join a sales program table to a calendar table so that there would be a joined table with the full trailing 52 weeks by day, and then the sales data would be joined to it. The idea would be that there are nulls I could COALESCE after the fact. However, my problem is that I only get results without nulls from my sales data table.
The questions I've consulted so far are:
Join to Calendar Table - 5 Business Days
Joining missing dates from calendar table Which points to
MySQL how to fill missing dates in range?
My Calendar table is all 364 days previous to today (today being day 0). And the sales data has a program field, a store field, and then a start date and an end date for the program.
Here's what I have coded:
SELECT
CAL.DATE,
CAL.DAY,
SALES.ITEM,
SALES.PROGRAM,
SALES.SALE_DT,
SALES.EFF_BGN_DT,
SALES.EFF_END_DT
FROM
CALENDAR_TABLE AS CAL
LEFT JOIN
SALES_TABLE AS SALES
ON CAL.DATE = SALES.SALE_DT
WHERE 1=1
and SALES.ITEM = 1 or SALES.ITEM is null
ORDER BY DATE ASC
What I expected was 365 records with dates where there were nulls and dates where there were filled in records. My query resulted in a few dates with null values but otherwise just the dates where a program exists.
DATE | ITEM | PROGRAM | SALE_DT | PRGM_BGN | PRGM_END |
----------|--------|---------|----------|-----------|-----------|
8/27/2020 | | | | | |
8/26/2020 | | | | | |
8/25/2020 | | | | | |
8/24/2020 | | | | | |
6/7/2020 | 1 | 5 | 6/7/2020 | 2/13/2016 | 6/7/2020 |
6/6/2020 | 1 | 5 | 6/6/2020 | 2/13/2016 | 6/7/2020 |
6/5/2020 | 1 | 5 | 6/5/2020 | 2/13/2016 | 6/7/2020 |
6/4/2020 | 1 | 5 | 6/4/2020 | 2/13/2016 | 6/7/2020 |
Date = Calendar day.
Item = Item number being sold.
Program = Unique numeric ID of program.
Sale_Dt = Field populated if at least one item was sold under this program.
Prgm_bgn = First day when item was eligible to be sold under this program.
Prgm_end = Last day when item was eligible to be sold under this program.
What I would have expected would have been records between June 7 and August 24 which just had the DATE column populated for each day and null values as what happens in the most recent four records.
I'm trying to understand why a calendar table and what I've written are not providing the in-between dates.
EDIT: I've removed the request for feedback to shorten the question as well as an example I don't think added value. But please continue to give feedback as you see necessary.
I'd be more than happy to delete this whole question or have someone else give a better answer, but after staring at the logic in some of the answers in this thread (MySQL how to fill missing dates in range?) long enough, I came up with this:
SELECT
CAL.DATE,
t.* EXCEPT (DATE)
FROM
CALENDER_TABLE AS CAL
LEFT JOIN
(SELECT
CAL.DATE,
CAL.DAY,
SALES.ITEM,
SALES.PROGRAM,
SALES.SALE_DT,
SALES.EFF_BGN_DT,
SALES.EFF_END_DT
FROM
CALENDAR_TABLE AS CAL
LEFT JOIN
SALES_TABLE AS SALES
ON CAL.DATE = SALES.SALE_DT
WHERE 1=1
and SALES.ITEM = 1 or SALES.ITEM is null
ORDER BY DATE ASC) **t**
ON CAL.DATE = t.DATE
From what I can tell, it seems to be what I needed. It allows for the subquery to connect a date to all those records, then just joins on the calendar table again solely on date to allow for those nulls to be created.

SQL (Snowflake) – 30 day look ahead / rolling average

I have two tables – purchases and activity.
The purchase table is structured like so:
|----------|----------------|----------|
| user_id | purchase_date | status |
|----------|----------------|----------|
| 1234 | 2020-01-01 | active |
|----------|----------------|----------|
| 2345 | 2020-01-10 | cancelled|
The activity table is structured like so:
|----------|----------------|-----------------|
| user_id | date | videos_viewed |
|----------|----------------|-----------------|
| 1234 | 2020-01-02 | 4 |
|----------|----------------|-----------------|
| 2345 | 2020-01-03 | 3 |
|----------|----------------|-----------------|
| 2345 | 2020-01-10 | 10 |
|----------|----------------|-----------------|
| 2345 | 2020-01-11 | 7 |
I am looking to query out a first 30 day activity average for each users' first 30 days based on a set purchase period.
The query I have written so far is this:
SELECT avg(t3.viewsperday)
FROM
(SELECT
date
,sum(t1.videos_viewed)/count(t1.user_id) as viewsperday
FROM activity t1
INNER JOIN (SELECT * FROM purchase c
WHERE status = 'active'
AND purchase_date BETWEEN '2020-01-01' and '2020-02-01') t2
ON t1.user_id = t2.user_id
where date between '2020-01-01' and '2020-02-01'
group by 1
order by 1 asc) as t3;
However, the problem here is that if a user purchased on 2020-01-31 I only get the first day of activity. I need help to figure out how to get the rolling average / look ahead 30 days from each purchase date – and get the average activity from those 30 days.
I suspect a window function would be appropriate here, but I am not sure how to formulate it as it is a bit outside of my knowledge. Any help would be greatly appreciated.
the following should work. I'm assuming that you want the average over 30 days even when there may have been zero views on some of those days? You may also need to adjust it slightly depending on exactly how you are defining the 30 day date range i.e. is the 30th day included, is the purchase date included, etc.
I've written it as an outer join so that even users with no views will be included
SELECT
P.USER_ID,
SUM(A.VIDEOS_VIEWED)/30
FROM PURCHASE P
LEFT OUTER JOIN ACTIVITY A ON P.USER_ID = A.USER_ID AND
A.DATE >= P.PURCHASE_DATE AND A.DATE <= dateadd(DAY, 30, P.PURCHASE_DATE)
GROUP BY P.USER_ID;
Update...
To get daily averages, try this (views on purchase date show as day 0, add 1 to the Day_after_Purchase formula if this should be day 1):
SELECT
(a.date - p.purchase_date) as Day_after_Purchase,
avg(A.VIDEOS_VIEWED)
FROM PURCHASE P
LEFT OUTER JOIN ACTIVITY A ON P.USER_ID = A.USER_ID AND
A.DATE >= P.PURCHASE_DATE AND A.DATE <= dateadd(DAY, 30, P.PURCHASE_DATE)
GROUP BY 1;

SQL Query Extract Totals by Month for Multiple Date Fields

I have an Oracle Database I am trying to query multiple date fields by dates and get the totals by month and year as output.
This was my original query. This just gets what I want for the dates I want to input.
SELECT COUNT(*) as Total
FROM Some_Table s
WHERE (s.Start_DATE <= TO_Date ('2019/09/01', 'YYYY/MM/DD'))
AND (s.End_DATE IS NULL OR (s.End_DATE > TO_Date ('2019/08/31', 'YYYY/MM/DD')))
I would like to get an output where it gives me a count by Month and Year. The count would be the number between the Start_DATE (beginning of the month) and the End_DATE (end of the month).
I can't do
Edit: this was an example from another query and has no relation to the query above. I was just trying to provide an example of what I cannot do because I have two separate date fields. The example below was stating my knowledge of extracting month and year from a single date field. Sorry for the confusion.
SELECT extract(year from e.DATE_OCCURRED) as Year
,to_char(e.DATE_OCCURRED, 'MONTH') as Month
,count (*) as totals
because the Start_DATE and End_DATE are two separate fields.
Any help would be appreciated
Edit: Example would be
----------------------------------
| Name | Start_DATE | End_DATE |
----------------------------------
| John | 01/16/2018 | 07/09/2019 |
| Sue | 06/01/2015 | 09/01/2018 |
| Joe | 04/06/2016 | Null |
----------------------------------
I want to know my total number of workers that would have been working by month and year. Would want the output to look like.
------------------------
| Year | Month | Total |
------------------------
| 2016 | Aug | 2 |
| 2018 | May | 3 |
| 2019 | Aug | 2 |
------------------------
So I know I had two workers working in August 2016 and three in May 2018.
Do you want this?
SELECT count(*)
from some_table
where year(e.DATE_OCCURRED) > year(start_date)
and year(e.DATE_OCCURRED) < year(end_date)
and month(e.DATE_OCCURRED) > month(start_date)
and month(e.DATE_OCCURRED) < month(end_date)
note: using month and year functions is generally better when working with dates. If you convert to characters you might find that January comes after February (as an example) since J comes after F in the alphabet.
Are you looking for this?(Hoping that end_date > start_date)
select extract (year from end_dt2)- extract(YEAR from st_dt1) as YearDiff ,
extract (month from end_dt2)- extract (month from st_dt1) as monthDiff from tab;

month vs month query (data in the same table)

I have the access table with the structure as bellow.
I want to do a query that will substract the VOLUME from last month (the month of the data in in SOURCE field) from the data that was inputed this month.
For the example above the result should be something like:
SOURCE | VERSION | SALES MODEL | DESTINATION | PERIOD | VOLUME |
-------+---------+-------------+-------------+--------+--------|
201309 | 1 | model 1 | eu | 201309 | -1 |
In the table I have more models, more months and more sources. I need to have the source and source-1 substraction all the time and the data should match to the model, destination and period.
So if I have 3 sources (instead of two as above) it should return the 201308-201307 and 201309-201308 results.
Is this possible in access?
You can join a table onto itself by using table aliases. Once you know this the only tricky thing is figuring out what month value comes immediately after another.
Select
t1.source,
t1.version,
t1.[sales model],
t1.destination,
t1.period,
t1.volume - t2.volume as volume
From
table t1
inner join
table t2
on
t1.Source = IIf(t2.source Mod 100 = 12, t2.Source + 89, t2.Source + 1) And
t1.version = t2.version and
t1.[sales model] = t2.[sales model] and
t1.destination = t2.destination and
t1.period = t2.period
Edit - fixed the next month test for December

Summing one tables value and grouping it with a single value of another table

I have two tables.
Table 1: Actuals
A table with all the employess and how many hours they have worked in a given month
| ID | empID | hours | Month |
--------------------------------------
Table 2:
A target table which has hour target per month. The target refers to an amount that the sum of all the hours worked by the employees should meet.
| ID | hours target | Month |
-----------------------------------
Is it possible to return the sum of all table 1's hours with the target of table 2 and group it by the month and return it in a single data set?
Example
| Month | Actual Hours | hours target |
-----------------------------------------
| 1 | 320 | 350 |
etc.
Hope that is clear enough and many thanks for considering the question.
This should work:
SELECT t.[month], sum(a.[hours]) as ActualHours, t.[hourstarget]
FROM [TargetTable] t
JOIN [ActualsTable] a on t.[month] = a.[month]
GROUP BY t.[month], t.[hourstarget]
Written in plain English, you're saying "give me the sum of all hours accrued, grouped by the month (and also include the target hours for that month)".
WITH
t1 AS (SELECT mnth, targetHours FROM tblTargetHours),
t2 AS (SELECT mnth, sum(hours) AS totalhours FROM tblEmployeeHours GROUP BY mnth)
SELECT t1.mnth, t2.totalhours, t1.targethours
FROM t1, t2
WHERE t1.mnth = t2.mnth
results:
mnth totalhours targethours
1 135 350
2 154 350
3 128 350