How to make projections with future dates using Redshift - sql

I currently have a table called quantities with the following data:
+------+----------+----------+
| item | end_date | quantity |
+------+----------+----------+
| 1 | 26/11/17 | 100 |
+------+----------+----------+
| 2 | 28/11/17 | 300 |
+------+----------+----------+
| 3 | 30/11/17 | 500 |
+------+----------+----------+
I want to query it so I can get this result:
+--------+-------+
| date | total |
+--------+-------+
| 26-Nov | 900 |
+--------+-------+
| 27-Nov | 800 |
+--------+-------+
| 28-Nov | 800 |
+--------+-------+
| 29-Nov | 500 |
+--------+-------+
| 30-Nov | 500 |
+--------+-------+
How would this query look like? Many thanks!
Please note:
The above output is the result of suming the "quantity" field of each item when today's date is =< end_date. See below that today is the 26th of november.
+--------+-----+-----+-----+-------+
| date | 1 | 2 | 3 | total |
+--------+-----+-----+-----+-------+
| 26-Nov | 100 | 300 | 500 | 900 |
+--------+-----+-----+-----+-------+
| 27-Nov | - | 300 | 500 | 800 |
+--------+-----+-----+-----+-------+
| 28-Nov | - | 300 | 500 | 800 |
+--------+-----+-----+-----+-------+
| 29-Nov | - | - | 500 | 500 |
+--------+-----+-----+-----+-------+
| 30-Nov | - | - | 500 | 500 |
+--------+-----+-----+-----+-------+
I'd need the query to always give an output with the following date range:
start_date=current_date
end_date=the latest end_date from the list of items
I am using PostgreSQL 8.0.2 on i686-pc-linux-gnu, compiled by GCC gcc (GCC) 3.4.2 20041017 (Red Hat 3.4.2-6.fc3), Redshift 1.0.1499

t=# create table so (item serial, end_date date, quantity int);
CREATE TABLE
t=# set datestyle TO DMY;
SET
t=# insert into so(end_date,quantity) values('26-11-2017',100),('28-11-2017', 300), ('30-11-2017', 500);
INSERT 0 3
then, we create a view with a date series that goes into the future starting from today by using a table with a sequential id column:
CREATE VIEW future_dates AS
SELECT (getdate()::date -1 + id)::date as future_dates
FROM app_data.table_with_sequential_id
ORDER BY future_dates
N.b. We need to create the above view because generate_series is not fully supported in Redshift.
and lastly select itself:
t=# select gs::date, sum(quantity) over (order by gs desc rows unbounded preceding)
from future_dates gs
left outer join so on so.end_date = gs
order by gs ;
gs | sum
------------+-----
2017-11-26 | 900
2017-11-27 | 800
2017-11-28 | 800
2017-11-29 | 500
2017-11-30 | 500
(5 rows)

Related

how to do dynamic sum and substraction [duplicate]

I have a table in an Oracle db that has the following fields of interest: Location, Product, Date, Amount. I would like to write a query that would get a running total of amount by Location, Product, and Date. I put an example table below of what I would like the results to be.
I can get a running total but I can't get it to reset when I reach a new Location/Product. This is the code I have thus far, any help would be much appreciated, I have a feeling this is a simple fix.
select a.*, sum(Amount) over (order by Location, Product, Date) as Running_Amt
from Example_Table a
+----------+---------+-----------+------------+------------+
| Location | Product | Date | Amount |Running_Amt |
+----------+---------+-----------+------------+------------+
| A | aa | 1/1/2013 | 100 | 100 |
| A | aa | 1/5/2013 | -50 | 50 |
| A | aa | 5/1/2013 | 100 | 150 |
| A | aa | 8/1/2013 | 100 | 250 |
| A | bb | 1/1/2013 | 500 | 500 |
| A | bb | 1/5/2013 | -100 | 400 |
| A | bb | 5/1/2013 | -100 | 300 |
| A | bb | 8/1/2013 | 250 | 550 |
| C | aa | 3/1/2013 | 550 | 550 |
| C | aa | 5/5/2013 | -50 | 600 |
| C | dd | 10/3/2013 | 999 | 999 |
| C | dd | 12/2/2013 | 1 | 1000 |
+----------+---------+-----------+------------+------------+
Ah, I think I have figured it out.
select a.*, sum(Amount) over (partition by Location, Product order by Date) as Running_Amt
from Example_Table a
from Advanced SQL Functions in Oracle 10g book, it has this example.
SELECT dte "Date", location, receipts,
SUM(receipts) OVER(ORDER BY dte
ROWS BETWEEN UNBOUNDED PRECEDING
AND CURRENT ROW) "Running total"
FROM store
WHERE dte < '10-Jan-2006'
ORDER BY dte, location
I could type out all the answer or send you to where I learned it. :)
Check this out, it explains exactly what you are trying to do.
http://www.codeproject.com/Articles/300785/Calculating-simple-running-totals-in-SQL-Server

How to set a SQL statement into other statement to create a view

I'm trying to write a SQL statement that includes another statement, to get from that all a view. I have 1 data Table. this table have 3 rows(see: Table 1). What I'm trying to do is create a view which select all dates one time DISTINCT. now for every selected date row, select all rows where date = date and sum all price.
For example: the Main table
+----+--------------+---------------+------------+
| id | article_name | article_price | date |
+----+--------------+---------------+------------+
| 1 | T-Shirt | 10 | 2020-11-16 |
| 2 | Shoes | 25 | 2020-11-16 |
| 3 | Pullover | 35 | 2020-11-17 |
| 4 | Pants | 10 | 2020-11-18 |
+----+--------------+---------------+------------+
What im expecting is to have 3 rows(because the first 2 rows have the same date)
+------------+-----+
| date | sum |
+------------+-----+
| 2020-11-16 | 35 |
| 2020-11-17 | 35 |
| 2020-11-18 | 10 |
+------------+-----+
I'm having a hard time to think about an "Algorithm" to solve this.
any ideas?
Use group by!
select date, sum(article_price) as sum_article_price
from mytable
group by date

SQL Server 2014 - How to calculate percentage based on last NOT NULL value in a column?

I have the following table dates, items and sales as show below :
table Dates :
+---------+------------+------------+
| Date_ID | StartDates | EndDates |
+---------+------------+------------+
| 1 | 2016-07-01 | 2016-07-05 |
| 2 | 2016-07-06 | 2016-07-12 |
+---------+------------+------------+
table items :
+--------+----------+---------+
| ITM_ID | ITM_Name | ITM_Qty |
+--------+----------+---------+
| A0001 | Item A | 30 |
| B0001 | Item B | 50 |
+--------+----------+---------+
table sales :
+----------+------------+------------+-----------+
| Sales_ID | Sales_Date | Sales_Item | Sales_Qty |
+----------+------------+------------+-----------+
| S0001 | 2016-07-02 | A | 5 |
| S0002 | 2016-07-04 | A | 15 |
| S0003 | 2016-07-08 | B | 20 |
| S0004 | 2016-07-12 | A | 10 |
+----------+------------+------------+-----------+
I would like to calculate a percentage (act like a ratio of sales on current period compared to the previous period) and the available amount of item after each sales.
My expected output would be like this :
+------------+------------+---------+----------+----------+-----------+
| StartDates | EndDates | Item_ID | Sold_Qty | Percents | Available |
+------------+------------+---------+----------+----------+-----------+
| 2016-07-01 | 2016-07-05 | A0001 | 20 | 100 | 10 |
| 2016-07-01 | 2016-07-05 | B0001 | 0 | 0 | 50 |
| 2016-07-06 | 2016-07-12 | A0001 | 10 | 50 | 0 |
| 2016-07-06 | 2016-07-12 | B0001 | 20 | 100 | 30 |
+------------+------------+---------+----------+----------+-----------+
I hope the expected output will be possible but I have currently not get a working query yet.
As the table above, the column percents is a percentage sales of current period compared to the last period, i.e. on item A0001 first period has sold_qty is 20 and the second period is 10, therefore the percentage of second period is (10/20) * 100 = 50.
EDIT : for the case of item B0001, the sold_qty of the first period is 0, therefore the percentage count should not consider the value on the first period.
Try Below. For Calculating Percents i have used case statement that you can simplify it based on your requirement.
SELECT *,
CASE
WHEN SOLD_QTY = 0 THEN 0
WHEN LAG(SOLD_QTY)
OVER(
PARTITION BY ITM_ID
ORDER BY ITM_ID) = 0
OR LAG(SOLD_QTY)
OVER(
PARTITION BY ITM_ID
ORDER BY ITM_ID) IS NULL THEN 100
ELSE CONVERT(FLOAT, SOLD_QTY) / NULLIF(LAG(SOLD_QTY)
OVER(
PARTITION BY ITM_ID
ORDER BY ITM_ID), 0) * 100
END PERCENTS
FROM (SELECT T1.STARTDATES,
T1.ENDDATES,
T2.ITM_ID,
ISNULL(SUM(T3.SALES_QTY), 0) SOLD_QTY,
( T2.[ITM_QTY] ) - ISNULL(SUM(T3.SALES_QTY), 0)AS AVIL
FROM #TABLE1 T1
CROSS JOIN #TABLE2 T2
LEFT JOIN #TABLE3 T3
ON T3.[SALES_ITEM] = LEFT(T2.[ITM_ID], 1)
AND T3.SALES_DATE BETWEEN T1.STARTDATES AND T1.ENDDATES
GROUP BY T1.STARTDATES,
T1.ENDDATES,
T2.ITM_ID,
T2.[ITM_QTY])A

Create a temp table with data range using startdate and enddate from different records in SQL Server

I've got to write a command in Crystal Reports which should create some sort of temporary table to be used on the report itself.
I basicaly need:
VATDates:
+------------+------------+----------+---------+
| StartDate | EndDate | VATCode | Rate |
+------------+------------+----------+---------+
| 01/12/2008 | 31/12/2009 | GB001 | 15 |
| 01/01/2010 | 31/12/2011 | GB001 | 17.5 |
| 01/01/2012 |GETDATE()+1 | GB001 | 20 |
+----------------------------------------------+
What I have:
VATDates:
+------------+----------+---------+
| Date | VATCode | Rate |
+------------+----------+---------+
| 01/12/2008 | GB001 | 15 |
| 01/01/2010 | GB001 | 17.5 |
| 01/01/2012 | GB001 | 20 |
+---------------------------------+
How can I get something with the result of the 1st table from data I have on the 2nd in a SQL statement?
You can use a subselect to get EndDate.
select
v1.StartDate,
isnull((select top 1 v2.StartDate - 1 from VATDates as v2 where v2.StartDate > v1.StartDate order by v2.StartDate), '9999-12-31') as EndDate,
v1.VATCode,
v1.Rate
from
VATDates as v1

Running Total by Group SQL (Oracle)

I have a table in an Oracle db that has the following fields of interest: Location, Product, Date, Amount. I would like to write a query that would get a running total of amount by Location, Product, and Date. I put an example table below of what I would like the results to be.
I can get a running total but I can't get it to reset when I reach a new Location/Product. This is the code I have thus far, any help would be much appreciated, I have a feeling this is a simple fix.
select a.*, sum(Amount) over (order by Location, Product, Date) as Running_Amt
from Example_Table a
+----------+---------+-----------+------------+------------+
| Location | Product | Date | Amount |Running_Amt |
+----------+---------+-----------+------------+------------+
| A | aa | 1/1/2013 | 100 | 100 |
| A | aa | 1/5/2013 | -50 | 50 |
| A | aa | 5/1/2013 | 100 | 150 |
| A | aa | 8/1/2013 | 100 | 250 |
| A | bb | 1/1/2013 | 500 | 500 |
| A | bb | 1/5/2013 | -100 | 400 |
| A | bb | 5/1/2013 | -100 | 300 |
| A | bb | 8/1/2013 | 250 | 550 |
| C | aa | 3/1/2013 | 550 | 550 |
| C | aa | 5/5/2013 | -50 | 600 |
| C | dd | 10/3/2013 | 999 | 999 |
| C | dd | 12/2/2013 | 1 | 1000 |
+----------+---------+-----------+------------+------------+
Ah, I think I have figured it out.
select a.*, sum(Amount) over (partition by Location, Product order by Date) as Running_Amt
from Example_Table a
from Advanced SQL Functions in Oracle 10g book, it has this example.
SELECT dte "Date", location, receipts,
SUM(receipts) OVER(ORDER BY dte
ROWS BETWEEN UNBOUNDED PRECEDING
AND CURRENT ROW) "Running total"
FROM store
WHERE dte < '10-Jan-2006'
ORDER BY dte, location
I could type out all the answer or send you to where I learned it. :)
Check this out, it explains exactly what you are trying to do.
http://www.codeproject.com/Articles/300785/Calculating-simple-running-totals-in-SQL-Server