Subtotal Using Query - sql

I have a table like this:
Date Document No. Item Quantity Price
1/2/2019 1 ADUKU SS 1 1450
1/2/2019 1 AL GUIDE 1 250
1/2/2019 2 AL FLAT 1 75.65
1/2/2019 2 BATTERY(SMALL) 2 7.52
1/2/2019 2 Item 2 2 72.15
1/2/2019 2 Item3 2 58.75
1/6/2019 3 PAPER WHITE 0.25 1250
I need the output as along with subtotal like this:
Date Document No. Item Quantity Price
1/2/2019 1 ADUKU SS 1 1450
1/2/2019 1 AL GUIDE 1 250
1/2/2019 2 AL FLAT 1" 3 MM 1 75.65
1/2/2019 2 BATTERY 2 7.52
1/2/2019 2 Item 2 2 72.15
1/2/2019 2 Item3 2 58.75
1/2/2019 Subtotal 1914.07
1/6/2019 3 PAPER WHITE 0.25 1250
1/6/2019 Subtotal 1250
How to get the desired output like this using sql query?
I need to get subtotal based on the date.
What I tried so far is as follows :
SELECT T0.[DocDate] AS 'Date', T1.[DocNum] AS 'Document No', T0.[Dscription] AS 'Item',
T0.[Quantity] AS 'Quantity', T0.[StockPrice] AS 'Inventory Price'
FROM [table_1] T0
INNER JOIN [table_2] T1
ON T1.[DocEntry] = T0.[DocEntry]
UNION ALL
SELECT T1.[DocDate] as 'Date', NULL,NULL,NULL, SUM(T0.StockPrice)
FROM [table_1] T0
INNER JOIN [table_2] T1
ON T1.[DocEntry] = T0.[DocEntry]
GROUP BY T1.[DocDate]

You can use a UNION to your table and the sums:
select *
from documents
union all
select
date,
null documentno,
'Subtotal' item,
null quantity,
sum(price) price
from documents
group by date
order by
date,
case when documentno is null then 1 else 0 end,
documentno
See the demo

The syntax suggests that this is not a MySQL query. Assuming SQL Server (which is consistent with the square braces), uou can use grouping sets, but you need an aggregation query:
SELECT T1.DocDate, T1.DocNum, T2.Dscription AS Item,
SUM(T1.Quantity) AS Quantity,
T1.StockPrice AS InventoryPrice
FROM [table_1] T1 INNER JOIN
[table_2] T2
ON T2.[DocEntry] = T1.[DocEntry]
GROUP BY GROUPING SETS ( (T1.DocDate, T1.DocNum, T2.Dscription), (T1.DocDate, T2.Dscription) );

Related

Calculate total donations based on an attribute table

I am trying to get a list of donors who have cumulatively donated $5K+ between two different campaigns. My data is something like this
Attributes table
transactionid
attributevalue
123231
campaign 1
123456
campaing 2
123217
campaign 1
45623
campaing 2
65791
campaing 3
78931
campaign 4
11111
campaign 5
22222
campaing 6
Donations table
transactionid
donationamount
donorid
123231
2000
1233
123456
30000
1456
45623
8000
1233
78931
90
8521
11111
20
1233
22222
68
1456
Donor table
donorid
name
1233
John
1456
Mary
8521
Karl
This is what I tried, but the total I am getting is not right at all.
WITH test AS (
SELECT don.donorid,don.donationamount,a.attributevalue
FROM attributes table a
INNER JOIN donations don ON don.transactionid=a.transactionid
)
SELECT d.donorid,
SUM(CASE WHEN test.attributevalue='campaign 1' OR test.attributevalue='campaign 2'
THEN test.donationamount END) AS campaing_donation,
SUM(test.donationamount) AS total_donations
FROM donortable d
INNER JOIN test ON d.donorid = test.donorid
GROUP BY d.donorid
HAVING SUM(CASE WHEN test.attributevalue = 'campaign 1' OR test.attributevalue = 'campaign 2' THEN test.donationamount END) > 5000
but this is not working. My total donations sum is giving a value that is several times higher than the actual value.
Ideally, the final result would be something like this:
donorid
campaign_amount
totalamount
1233
10000
10020
1456
30000
30068
Select
sum (Donations.donationamount),
donor.donorid,
donor.name
from
Attributes
join Donations on
Donations.transactionid = attributes.transactionid
Join Donor on
donor.donorid = donations.donorid
Where
Attribute.attributevalue in ('campaign 1','campaign 2')
Group by
donor.donorid,
donor.name
create table #transection_tbl(tran_id int,attributevalue varchar(20))
create table #donation_tbl(tran_id int,donation_amount int ,donar_id int)
select donar_id,max(donation_amount) as 'campaing_amount',
sum(donation_amount) as 'totalamount'
from #transection_tbl as t1
inner join #donation_tbl as t2 on t1.tran_id=t2.tran_id
group by donar_id
having COUNT(attributevalue)=2

Calculate SUM between two dates SQL SERVER

I'm having two tables
Calendar
FirstDate | LastDate
------------+-----------
2020-05-01 2020-05-03
2020-05-02 2020-05-04
ProfileRate
ID | Date | Rate | Product
---+------------+------+----------
1 2020-05-01 100 Prod1
2 2020-05-02 200 Prod1
3 2020-05-03 300 Prod1
4 2020-05-04 400 Prod1
5 2020-05-01 150 Prod2
6 2020-05-02 250 Prod2
7 2020-05-03 350 Prod2
8 2020-05-04 450 Prod2
I want to calculate SUM. Something like this
FirstDate | LastDate | Prod1 | Prod2
------------+-------------+--------+-------
2020-05-01 2020-05-03 600 750
2020-05-02 2020-05-04 900 1050
What I've tried:
SELECT [Date], SUM([Rate])
FROM [ProfileRate]
WHERE [Date] BETWEEN '2020-05-01' AND '2020-05-04'
GROUP BY [Date]
Please help me. Thanks
you have to do several steps to solve the problem:
combine calendar records with profiles
establish which profiles meet the calendar range
total the value for each profile and date range
finally establish the detailed information of the calendar
this query meets the conditions
with DataForCalendar as
(
SELECT IdCalendar,FirstDate,LastDate,Id,DateRate,Rate,Product
FROM
Calendar CROSS JOIN ProfileRate
where DateRate between '2020-05-01' and '2020-05-05'
),
DetailForCalendar as
(
select IdCalendar,Rate,Product
from DataForCalendar
where DateRate between FirstDate and LastDate
),
TotalForCalendar as
(
select IdCalendar,Product,sum(Rate)As Total from DetailForCalendar
GROUP BY IdCalendar,Product
)
select Calendar.IdCalendar,Calendar.FirstDate,Calendar.LastDate,
TotalForCalendar.Product,TotalForCalendar.Total
from TotalForCalendar inner join
Calendar on TotalForCalendar.IdCalendar=Calendar.IdCalendar;
in this example you can find step by step how it work
in this example there is one more product and one more calendar.
I think this is a JOIN and conditional aggregation:
SELECT c.FirstDate, c.LastDate,
SUM(CASE WHEN pr.prod = 'Prod1' THEN pr.Rate END) as prod1,
SUM(CASE WHEN pr.prod = 'Prod2' THEN pr.Rate END) as prod2
FROM Calender c LEFT JOIN
ProfileRate pr
ON pr.Date >= c.FirstDate AND pr.Date <= c.LastDate
GROUP BY c.FirstDate, c.LastDate;
Do the join & conditional aggregation :
select c.fisrtdate, c.lastdate,
sum(case when pr.product = 'prod1' then rate else 0 end) as prod1,
sum(case when pr.product = 'prod2' then rate else 0 end) as prod2
from calendar c join
ProfileRate pr
on pr.date >= c.fisrtdate and pr.date <= c.lastdate
group by c.fisrtdate, c.lastdate;
If you want all calendar dates then use left join instead.

Tracing original Value through Iteration SQL

Suppose there is a data collection system that, whenever a record is altered, it is then saved as a new record with a prefix (say M-[most recent number in que and is unique]).
Suppose I am given the following data set:
Customer | Original_Val
1 1020
2 1011
3 1001
I need to find the most recent value for each customer given the following table:
Customer | Most_Recent_Val | Pretained_To_Val | date
1 M-2000 M-1050 20170225
1 M-1050 M-1035 20170205
1 M-1035 1020 20170131
1 1020 NULL 20170101
2 M-1031 1011 20170105
2 1011 NULL 20161231
3 1001 NULL 20150101
My desired output would be:
Customer | Original_Val | Most_Recent_Val | date
1 1020 M-2000 20170225
2 1011 M-1031 20170105
3 1001 1001 20150101
For customer 1, there are 4 levels i.e (M-2000 <- M-1050 <- M-1035 <- 1020) Note that there would be no more than 10 levels of depth for each customer.
Much Appreciated! Thanks in advance.
Find the min and max of each customer and then join it together. Something like this:
Select
[min].Customer
,[min].Most_Recent_Val as Original_Val
,[max].Most_Recent_Val as Most_Recent_Val
,[max].date
From
(
Select
Customer
,Most_Recent_Val
,date
From
table t1
inner join (
Select
Customer
,MIN(date) as MIN_Date
From
table
Group By
Customer
) t2 ON t2.Customer = t1.Customer
and t2.MIN_Date = t1.Date
) [min]
inner join (
Select
Customer
,Most_Recent_Val
,date
From
table t1
inner join (
Select
Customer
,MAX(date) as MAX_Date
From
table
Group By
Customer
) t2 ON t2.Customer = t1.Customer
and t2.MAX_Date = t1.Date
) [max] ON [max].Customer = [min].Customer

Zero Fill Data for Missing Dates

I have two tables:
Cust Sales Week
123 4 1/8/2015
123 3 1/22/2015
234 4 1/1/2015
.
Week
1/1/2015
1/8/2015
1/15/2015
1/22/2015
I want to combine them so that every Cust has every date and where there are no Sales it is filled with 0.
Cust Sales Week
123 4 1/1/2015
123 0 1/8/2015
123 0 1/15/2015
123 3 1/22/2015
234 4 1/1/2015
234 0 1/8/2015
234 0 1/15/2015
234 0 1/22/2015
Is there a way I can 'select distinct(Cust)' and join them somehow?
First, generate the rows you want using a cross join. Then bring in the data you want using a left join:
select c.cust, w.week, coalesce(t.sales, 0) as sales
from weeks w cross join
(select distinct cust from t) c left join
t
on t.cust = c.cust and t.week = w.week;
You can left join on the dates table and use isnull on the sales column. Use an equivalent of isnull in Netezza.
select t1.cust, isnull(t1.sales,0), t2.week
from daystable2 t2 left join salestable1 t1 on t1.week = t2.week
I think this will do the trick
SELECT week, cust, COALESCE(sales, 0)
FROM week_tbl a LEFT JOIN cust_table b
ON a.week = b.week

Adding duplicate values in sql

I'm just a newbie in programming and I'm having a problem with this (see table below).
DocNum DocDate Quantity ItemGroupCode ItemGroupName
89226 7-Nov-12 10 103 Fish-Fillet
88768 8-Nov-12 1 104 Fish-Regular
88856 6-Nov-12 2 104 Fish-Regular
88678 20-Nov-12 12 109 Value Added
89415 5-Nov-12 12 109 Value Added
88642 5-Nov-12 1 112 Other Charges
88646 5-Nov-12 20 112 Other Charges
88729 7-Nov-12 5.64 112 Other Charges
88804 12-Nov-12 10 112 Other Charges
88992 12-Nov-12 1 112 Other Charges
I want to combine similar Code of ItemGroupCode column then Add its Quantity.
EX.
Quantity ItemGroupCode ItemGroupName
10 103 Fish-Fillet
3 104 Fish-Regular
24 109 Value Added
38.64 112 Other Charges
Thanks ...
Pipay
Try this:
select sum(quantity) quantity, itemgroupcode, itemgroupname
from table_name
group by itemgroupcode, itemgroupname
For your question if I understand correctly, you need from the select you provide in your comments, to have the output of the first question. If this is the case then try something like this:
SELECT SUM(quantity), ItemGroupCode, ItemClass
FROM
(SELECT A.DocNum, A.DocDate, B.Quantity,B.Price,B.Linetotal, A.Doctotal, C.ItemName, C.ItmsGrpCod as ItemGroupCode,
D.ItmsGrpnam as ItemClass
FROM OINV as A LEFT outer JOIN INV1 As B ON A.DocEntry = B.DocEntry
LEFT OUTER JOIN OITM As C ON B.ItemCode = C.ItemCode
LEFT OUTER JOIN OITB As D ON C.ItmsGrpCod = D.ItmsGrpCod
WHERE A.DocDate >= '11/01/2012'
group by A.DocNum, A.DocDate, B.Quantity,B.Price,B.Linetotal, A.Doctotal, C.ItemName, C.ItmsGrpCod, D.ItmsGrpnam
order by C.ItmsGrpCod ASC) X
GROUP BY X.ItemGroupCode, X.ItemClass