Access SQL Statement Calculate the Difference From Previous Month [duplicate] - sql

This question already has answers here:
Query for getting value from another record in same table and filter by difference greater than a gap threshold
(2 answers)
Closed 3 years ago.
I'm using Microsoft Access 2016 to developing a new program, each month the data entry enter in a row the date, the total budget plan and cumulative expending amount. I am trying to create a query showing the monthly bases experiences. For example in this month August, the cumulative value 170000, the cumulative value for July 125000, so I need a query showing the difference is 45000.
Attached an Access file for short data examples.
https://www.dropbox.com/s/h9vlp84fzmjc93d/Minus%20Calculation.accdb?dl=0
Thanks for your support in advance!
Best Regards
Mahmoud

Assuming that you always want to see the data from exactly one month previous (whether or not such data exists), and that the data could be entered on any day in the month, you might consider the following:
select
t1.date,
t1.cumulative_expending_amount,
t2.cumulative_expending_amount,
t1.cumulative_expending_amount-t2.cumulative_expending_amount
from
YourTable t1 left join YourTable t2 on
t1.date >= dateserial(year(t2.date),month(t2.date)+1,1) and
t1.date <= dateserial(year(t2.date),month(t2.date)+2,0)
Change YourTable, date, and cumulative_expending_amount to suit the name of your table and fields respectively.
Following your comments, it would appear that the following SQL satisfies your requirements:
select
t1.itemid,
t1.date,
t1.cumulative_expending_amount,
(
select top 1 t3.cumulative_expending_amount
from YourTable t3
where t3.itemid = t1.itemid and t3.date < t1.date
order by t3.date desc
) as last_cumulative_expending_amount,
t1.cumulative_expending_amount-last_cumulative_expending_amount as diff
from
YourTable t1 inner join
(
select t.itemid, max(t.date) as mdate
from YourTable t
group by t.itemid
) t2 on t1.itemid = t2.itemid and t1.date = t2.mdate
order by
t1.itemid,
t1.date desc

You can use a correlated subquery. Based on your description, the code looks like this:
select t.*,
(select top (1) t2.cumulative_spending
from t as t2
where t2.date < t.date
order by t2.date desc
) as prev_cumulative_spending
from t;

Related

SQL: Select from another table (t2) without joining but referencing a column from t1

I have a table with columns date and net_sales. For each day, I want to get the sum of the net_sales for the last 30 days.
This is my query:
thirty_days_net_sales AS (
SELECT
t1.date,
t1.net_sales AS net_sales_on_date,
(SELECT SUM(t2.net_sales) FROM total_net_sales_per_day t2 WHERE t2.date >= DATE_SUB(t1.date, INTERVAL 30 DAY) AND t2.date <= t1.date)
FROM
total_net_sales_per_day t1)
When I run this query I get the error: LEFT OUTER JOIN cannot be used without a condition that is an equality of fields from both sides of the join.
I am using Google BigQuery. Thanks in advance for your help!
Consider rather below approach
select *, sum(net_sales) over win last_30_days
from total_net_sales_per_day
window win as (order by unix_date(date) range between 29 preceding and current row )
You would use window functions. If you have data for every day (as the name of the table implies:
SELECT tnspd.*
sum(netsales) over (partition by date
order by date
rows between -30 and current row
)
FROM total_net_sales_per_day tnspd;
As the error said, you have to add and equal condition. In case of using join you have to use ON keyword for one equal condition.
In your query, because you do not have join explicitly, you must have an equal condition something like I added below:
thirty_days_net_sales AS (
SELECT
t1.date,
t1.net_sales AS net_sales_on_date,
(SELECT SUM(t2.net_sales) FROM total_net_sales_per_day t2 WHERE t2.date >= DATE_SUB(t1.date, INTERVAL 30 DAY) AND t2.date <= t1.date
AND t1.id==t2.id)
FROM
total_net_sales_per_day t1)
This link might help for more information:
https://sql.info/d/solved-bigquery-left-outer-join-cannot-be-used-without-a-condition-that-is-an-equality-of-fields-from-both-sides-of-the-join

Date Difference between consecutive rows adding additional columns

Say I added a Cost Difference column to the second table from Rishal (see the below link for this previous post), how would I also calculate and display that?
Using just the 1001 Account Number and adding the following amounts of ID1=$10, ID4=$33 and ID6=$50 to the first table, how would I display in Rishal's second table a result of $23 and $17 in addition to the other 3 columns that are already there?
I've used this code (from GarethD) and would like to insert my Cost Difference column within this...Thanks in advance,
SELECT ID,
AccountNumber,
Date,
NextDate,
DATEDIFF("D", Date, NextDate)
FROM ( SELECT ID,
AccountNumber,
Date,
( SELECT MIN(Date)
FROM YourTable T2
WHERE T2.Accountnumber = T1.AccountNumber
AND T2.Date > T1.Date
) AS NextDate
FROM YourTable T1
) AS T
Date Difference between consecutive rows
I would recommend using JOIN to bring in the entire next record:
SELECT T.*, DATEDIFF("D", t.Date, t.NextDate) as datediff,
TNext.Amount, (Tnext.Amount - T.Amount) as amountdiff
FROM (SELECT T1.*,
(SELECT MIN(Date)
FROM YourTable T2
WHERE T2.Accountnumber = T1.AccountNumber AND
T2.Date > T1.Date
) AS NextDate
FROM YourTable as T1
) AS T LEFT JOIN
YourTable as Tnext
ON t.Accountnumber = tnext.Accountnumber AND t.Date = tnext.Accountnumber;

How to show a row for the dates not in records of a table as zero

I am trying to show the records as zero for the dates not found.
Below is my basic query:
Select date_col, count(distinct file_col), count(*) from tab1
where date_col between 'date1' and 'date2'
group by date_col;
The output is for one date.
I want all the dates to be shown in result.
The general way to deal with this type of problem is to use something called a calendar table. This calendar table contains all the dates which you want to appear in your report. We can create a crude one by using a subquery:
SELECT
t1.date,
COUNT(DISTINCT t2.file_col) AS d_cnt,
COUNT(t2.file_col) AS cnt
FROM
(
SELECT '2018-06-01' AS date UNION ALL
SELECT '2018-06-02' UNION ALL
...
) t1
LEFT JOIN tab1 t2
ON t1.date = t2.date_col
WHERE
t1.date BETWEEN 'date1' and 'date2'
GROUP BY
t1.date;
Critical here is that we left join the calendar table to your table containing the actual data, but we count a column in your data table. This means that zero would be reported for any day not having matching data.
If you are using postgreSQL, you could generate series with necessary dates period.
SELECT
t1.date,
COUNT(DISTINCT t2.file_col) AS d_cnt,
COUNT(t2.file_col) AS cnt
FROM
(
select to_char( '?'::DATE + (interval '1' month * generate_series(0,11)),'yyyy-mm-dd')as month) x
...
) t1
LEFT JOIN tab1 t2
ON t1.date = to_char(t2.date_col,'yyyy-mm')
WHERE
t1.date BETWEEN 'date1' and 'date2'
GROUP BY
t1.date;
In this example show how to generate sequence for month period.

SQL query with 2 nested to queries on same table

This question is an extension capability related to my previous question here Update column with autonumber. Now with only one table this time:
Date Adds
6/1/18 0
6/5/18 1
6/7/18 0
...+60 records
10/1/18 0
I would like to create a table of Dates, 60 date records (for ex) beyond the Date with a number in the New in Field. Using the previous method, here is what I have:
Select t1.adds, t1.date from T1 where t1.adds > 0 AND
(select count(*)+1 from t1 as t2
where t2.Date <= t1.Date AND t2.date >=
(select date from t1 as t3 where t3.date > t2.date) = 60)
I think everything would work except for the 2nd conditional statement where I need the date to be greater than the corresponding date where Adds > 0. If executed I would expect my table to look like:
Date Adds
10/1/18 1
I think this works but unsure how efficient it is yet. I just made a tbltemp with Adds and Date where Adds > 0
SELECT q1.adds, t1.Date
FROM T1, tblTemp AS q1
WHERE (select count(*) from T1 as t2 where t2.date <= t1.date AND t2.date > q1.date)=60
I will do a little more testing with more records unless anyone has any better ideas?

How to add using the same row of data on SQL?

I am in need of showing the summation of contributions over time; however I would like to demonstrate it using this format.
Date Pay Total
8.1 100 100
8.8 150 250
8.15 50 300
So I have only two sets of data, the date and the amount paid.
I would like to show the change of total amount paid based of the payment amount.
I think I would need to use a subquery but I cannot get it to work for me!
Any suggestions?
You didn't specify a DBMS so this is ANSI SQL using a window function
select date,
pay,
sum(pay) over (order by date) as total
from the_table
order by date;
This assumes the 30 in the last line is just a typo and should actually be 300
These are portable ways to do it. I'm assuming that your dates are unique.
Inner join:
select t1."Date", min(t1.Pay) as Pay, sum(t1.Pay) as CumulativeTotal
from T t1 inner join T t2 on t2."Date" <= t1."Date"
group by t1."Date"
order by t1."Date"
Scalar subquery:
select
t1."Date", t1.Pay,
(select sum(Total) from T t2 where t2."Date" <= t1."Date") as CumulativeTotal
from T t1
order by t1."Date"