How to Sum two Different tax values amount individually - sql

I've been trying to sum two different tax values amount from one table and my table is like below
Sales table:
Customer_id Tax_percent Tax_amount
100 5% 2.50
100 14.5% 6.75
101 5% 1.25
102 5% 2.00
101 14.5% 9.50
My output will be like:
total 5% amount is 5.75
total 14.5% amount is 16.25
Please help.

Use SUM and GROUP By functions :
SELECT Tax_percent , SUM(Tax_amount)
FROM your_table
GROUP BY Tax_percent

declare #Salestable table(Customer_id int, Tax_percent numeric(5,2), Tax_amount numeric(5,2))
insert into #Salestable values( 100 , 5 , 2.50)
insert into #Salestable values( 100 , 14.5 , 6.75)
insert into #Salestable values( 101 , 5 , 1.25)
insert into #Salestable values( 102 , 5 , 2.00)
insert into #Salestable values( 101 , 14.5 , 9.50)
select Tax_percent,sum(Tax_amount) from #Salestable group by Tax_percent

Related

SQL Splitting Rows Into Multiple Rows Based on Condition

I have the below table:
Account
Credit
Debt
Net
ItemCount
InvoiceNumber
AAA
1300
150
1150
2
10
AAA
500
50
450
12
20
AAA
1800
650
1150
29
30
No record can have a higher count than 10 items so anything over 10 must be split into multiples of 10 until the last remaining value (which could be less than 10)
I am trying to automate this in SQL and have not been able to come up with an idea that works, I would like something to look at the above table and spit out the following:
Account
Credit
Debt
Net
ItemCount
InvoiceNumber
AAA
1300
150
1150
2
10
AAA
500
50
450
10
20
AAA
500
50
450
2
30
AAA
1800
650
1150
10
10
AAA
1800
650
1150
10
20
AAA
1800
650
1150
9
30
Any thoughts on how can this be accomplished?
I would try to use a cursor to iterate through the records and generate as many inserts as you need based on the value that you have
If you work with SQL Server, this should do the trick for you
CREATE TABLE #Table1
(
[Account] varchar(3),
[Credit] int,
[Debt] int,
[Net] int,
[ItemCount] int,
[InvoiceNumber] int
);
INSERT INTO #Table1 ([Account], [Credit], [Debt], [Net], [ItemCount], [InvoiceNumber])
VALUES
('AAA', 1300, 150, 1150, 2, 10),
('AAA', 500, 50, 450, 12, 20),
('AAA', 1800, 650, 1150, 29, 30)
;
WITH cte_numbers([Account] , [Credit] , [Debt] , [Net] , [ItemCount] , [InvoiceNumber] , itemcountzero, currentitmecount)
AS
(
SELECT
*,
(itemcount % 10) AS itemcountzero,
(itemcount) AS currentitmecount
FROM
#Table1
UNION ALL
SELECT
t.[Account] , t.[Credit] , t.[Debt] , t.[Net] , t.[ItemCount] , t.[InvoiceNumber] , c.itemcountzero, (c.currentitmecount-10)
FROM
#Table1 t
INNER JOIN
cte_numbers c ON t.[InvoiceNumber] = c.[InvoiceNumber]
AND (c.currentitmecount-10) >= c.itemcountzero
-- AND (currentitmecount-10) > 0
)
SELECT
[Account] , [Credit] , [Debt] , [Net] , IIF(currentitmecount > 10, 10 , currentitmecount) as [ItemCount] , [InvoiceNumber]
FROM
cte_numbers
ORDER BY
[InvoiceNumber], currentitmecount DESC;

Aggregation/Joins in Order and Shipping tables

I am new to SQL and I was facing a problem.
I have 2 tables as shown below,
Order_table
Ord_num
Ord_date
Customer_name
Order_total
1111
2021-03-11
ABC
1000
Shipping_table
Ord_num
Pkg_num
Pkg_weight
shipped_date
shipping_cost
1111
1
30
2021-03-12
10
1111
2
20
2021-03-13
8
I wrote the following query,
select sum(order_total), sum(pkg_weight), sum(shipping_cost)
from order_table O join shipping_table P
on O.Ord_num = P.Ord_num
By this, if I sum my Order total, it shows 2000 but Order was only for 1000.
I basically want my output to be,
Ord_num
Ord_date
Cust_name
Order_total
Pkg_num
shipped_date
pkg_weight
shipping_cost
1111
2021-03-11
ABC
1000
1
2021-03-12
30
10
1111
2021-03-11
ABC
0 or null
2
2021-03-13
20
8
The reason I want Order_total as 0 or null in the second line is because when I aggregate other columns like pkg_weight and shipping_cost, it should show their sum whereas for Order_total, it should not show as 2000 because the order was for 1000 but shipped in two different packages with 2 weights, 2 costs and shipped on 2 different days.
Can anyone help me what I should write my query as?
Thanks in advance.
Start with this:
Declare #order_table Table (Ord_num int, Ord_date date, Customer_name varchar(30), Order_total int);
Insert Into #order_table (Ord_num, Ord_date, Customer_name, Order_total)
Values (1111, '2021-03-11', 'ABC', 1000)
, (2222, '2021-04-11', 'XYZ', 2000);
Declare #shipping_table Table (Ord_Num int, Pkg_num int, Pkg_weight int, Shipped_date date, Shipping_cost int)
Insert Into #shipping_table (Ord_Num, Pkg_num, Pkg_weight, Shipped_date, Shipping_cost)
Values (1111, 1, 30, '2021-03-12', 10)
, (1111, 2, 20, '2021-03-13', 8)
, (2222, 1, 15, '2021-04-12', 5)
, (2222, 2, 10, '2021-04-13', 3);
Select ord.Ord_num
, ord.Ord_date
, ord.Customer_name
, Order_total = iif(shp.Pkg_num = 1, ord.Order_total, 0)
, shp.Pkg_num
, shp.Shipped_date
, shp.Pkg_weight
, shp.Shipping_cost
From #order_table ord
Inner Join #shipping_table shp On shp.Ord_Num = ord.Ord_num;
Which can then be converted to this for totals:
Select ord.Ord_num
, ord.Ord_date
, ord.Customer_name
, Order_total = sum(iif(shp.Pkg_num = 1, ord.Order_total, 0))
, Pkg_weight = sum(shp.Pkg_num)
, Shipping_cost = sum(shp.Shipping_cost)
From #order_table ord
Inner Join #shipping_table shp On shp.Ord_Num = ord.Ord_num
Group By
ord.Ord_num
, ord.Ord_date
, ord.Customer_name;

SQL query to calculate interval discount

I have trouble understanding how I can solve this problem with a T-SQL query.
I have a price column and a volume column. In another table a have discounts at different levels of volume. So my discount table could have values as
(StartLevel, DiscountFactor)
(0, 1);
(25, 0.95);
(50, 0.90);
(100, 0.75)
What I want is to calculate a total price. If Volume is 35, I want it to multiply
Price x ((35-25) x 0.95 + (25-0) x 1)
If the volume is 200, it should be
Price x ((200-100) x 0.75 + (100-50) x .9+(50-25) x .95+(25) x 1)
Can anybody help me with a query that solves this?
This can help:
DECLARE #products TABLE
(
id INT ,
price MONEY ,
volume INT
)
DECLARE #discounts TABLE
(
id INT ,
Level INT ,
Factor MONEY
)
INSERT INTO #products
VALUES ( 1, 10, 35 ),
( 2, 15, 200 )
INSERT INTO #discounts
VALUES ( 1, 0, 1 ),
( 2, 25, 0.95 ),
( 3, 50, 0.90 ),
( 4, 100, 0.75 )
SELECT p.id, p.price * SUM(ca.m)
FROM #products p
CROSS APPLY ( SELECT * ,
Factor * ( -Level + LEAD(Level) OVER ( PARTITION BY p.id ORDER BY Level, d ) ) AS m
FROM ( SELECT 1 AS d ,
Level ,
Factor
FROM #discounts
WHERE Level < p.volume
UNION ALL
SELECT 2 AS d ,
p.volume ,
0
) t
) ca
GROUP BY p.id, p.price
Without grouping it returns:
id price volume d Level Factor m
1 10.00 35 1 0 1.00 25.00
1 10.00 35 1 25 0.95 9.50
1 10.00 35 2 35 0.00 NULL
2 15.00 200 1 0 1.00 25.00
2 15.00 200 1 25 0.95 23.75
2 15.00 200 1 50 0.90 45.00
2 15.00 200 1 100 0.75 75.00
2 15.00 200 2 200 0.00 NULL
Then just group by product and sum of m results in:
id Total
1 345.00
2 2531.25
For a given Volume and Price you can get the discount based on interval using LEAD which is available in SQL Server 2012+ onwards.
Sample Data
DECLARE #PriceTable TABLE(Volume INT,Price DECIMAL(9,2) )
DECLARE #Discount TABLE(StartLevel int, DiscountFactor DECIMAL(9,2))
INSERT INTO #PriceTable
VALUES(75, 20.5),
(150, 20),
(250, 20.5),
(0, 15);
INSERT INTO #Discount
VALUES(0, 1),
(25, 0.95),
(50, 0.90),
(100, 0.75);
Query
SELECT Volume,Price,FinalPrice
FROM #PriceTable P
CROSS APPLY(
SELECT SUM(CASE WHEN (MaxLevel >=StartLevel) THEN (MaxLevel-StartLevel) ELSE 0 END *DiscountFactor)*P.Price as FinalPrice
FROM
(
SELECT CASE WHEN LEAD(StartLevel)OVER(ORDER BY StartLevel) < P.Volume THEN LEAD(StartLevel)OVER(ORDER BY StartLevel) ELSE P.Volume END MaxLevel,StartLevel, DiscountFactor
FROM #Discount
) IQ
)T
Output
Volume Price FinalPrice
75 20.50 1460.6250
150 20.00 2625.0000
250 20.50 4228.1250
0 15.00 0.0000

Select running balance from table credit debit columns

I have a SQL Server 2008 table, and I need to select a running balance from it
TransDate Credit Debit Datasource
------------------------------------------
2014-01-01 5000 NULL 3
2014-01-07 NULL 2000 3
2014-01-11 5000 NULL 3
2014-02-03 6000 NULL 4
2014-02-06 NULL 4000 4
2014-02-11 3000 NULL 4
2014-02-21 NULL 1000 3
2014-02-28 2000 NULL 3
2014-03-01 5000 NULL 3
I tried a correlated query
Select
t.TransDate,
t.Credit,
t.Debit,
(Select sum(coalesce(x.credit, 0) - coalesce(x.debit, 0))
From Transactions x
WHERE x.DataSource IN (3,4) AND (x.TransDate >= '2014/02/01' AND x.TransDate <= '2014/02/28' )
AND x.TransDate = t.TransDate) Balance
From
Transactions t
but I get all nulls for the Balance.
Expected output is
TransDate Credit Debit Balance
------------------------------------------
2014-01-11 NULL NULL 8000 <- opening balance
2014-02-03 6000 NULL 14000
2014-02-06 NULL 4000 10000
2014-02-11 3000 NULL 13000
2014-02-21 NULL 1000 12000
2014-02-28 2000 NULL 15000 <- closing balance
You need to self join table.
CREATE TABLE Test
(
TransDate DATE,
Credit INT,
Debit INT,
);
INSERT INTO Test VALUES
('2014-01-01', 5000, NULL),
('2014-01-07', NULL, 2000),
('2014-01-11', 5000, NULL),
('2014-02-03', 6000, NULL),
('2014-02-06', NULL, 4000),
('2014-02-11', 3000, NULL),
('2014-02-21', NULL, 1000),
('2014-02-28', 2000, NULL),
('2014-03-01', 5000, NULL)
WITH CTE AS
(
SELECT t2.TransDate,
t2.Credit,
t2.Debit,
SUM(COALESCE(t1.credit, 0) - COALESCE(t1.debit, 0)) AS Balance
FROM Test t1
INNER JOIN Test t2
ON t1.TransDate <= t2.TransDate
WHERE t1.DataSource IN (3,4)
GROUP BY t2.TransDate, t2.Credit, t2.Debit
)
SELECT *
FROM CTE
WHERE (TransDate >= '2014/01/11' AND TransDate <= '2014/02/28' )
OUTPUT
TransDate Credit Debit Balance
2014-01-11 5000 (null) 8000
2014-02-03 6000 (null) 14000
2014-02-06 (null) 4000 10000
2014-02-11 3000 (null) 13000
2014-02-21 (null) 1000 12000
2014-02-28 2000 (null) 14000
SQL FIDDLE
I would recommend to doing this:
Data Set
CREATE TABLE Test1(
Id int,
TransDate DATE,
Credit INT,
Debit INT
);
INSERT INTO Test1 VALUES
(1, '2014-01-01', 5000, NULL),
(2, '2014-01-07', NULL, 2000),
(3, '2014-01-11', 5000, NULL),
(4, '2014-02-03', 6000, NULL),
(5, '2014-02-06', NULL, 4000),
(6, '2014-02-11', 3000, NULL),
(7, '2014-02-21', NULL, 1000),
(8, '2014-02-28', 2000, NULL),
(9, '2014-03-01', 5000, NULL)
Solution
SELECT TransDate,
Credit,
Debit,
SUM(isnull(Credit,0) - isnull(Debit,0)) OVER (ORDER BY id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as Balance
FROM Test1
order by TransDate
OUTPUT
TransDate Credit Debit Balance
2014-01-01 5000 NULL 5000
2014-01-07 NULL 2000 3000
2014-01-11 5000 NULL 8000
2014-02-03 6000 NULL 14000
2014-02-06 NULL 4000 10000
2014-02-11 3000 NULL 13000
2014-02-21 NULL 1000 12000
2014-02-28 2000 NULL 14000
2014-03-01 5000 NULL 19000
Thank You!
Try this:
Select
x.TransDate,
x.Credit,
x.Debit,
SUM(coalesce(y.credit, 0) - coalesce(y.debit, 0)) AS Balance
FROM Transactions x
INNER JOIN Transasctions y
ON y.TransDate <= x.TransDate
AND Y.DataSource IN (3,4)
WHERE x.DataSource IN (3,4)
GROUP BY
x.TransDate,
x.Credit,
x.Debit
Note that, for large datasets this can get bad real quick... might want to use a cursor or try new 'Windowing' functions.
More here: https://brettwgreen.wordpress.com/2012/10/17/sql-cursors-are-slow-except-when-they-arent/
The Following Worked With Me:
WITH tempDebitCredit AS (
Select 0 As Details_ID, null As Creation_Date, null As Reference_ID, 'Brought Forward' As Transaction_Kind, null As Amount_Debit, null As Amount_Credit, isNull(Sum(Amount_Debit - Amount_Credit), 0) 'diff'
From _YourTable_Name
where Account_ID = #Account_ID
And Creation_Date < #Query_Start_Date
Union All
SELECT a.Details_ID, a.Creation_Date, a.Reference_ID, a.Transaction_Kind, a.Amount_Debit, a.Amount_Credit, a.Amount_Debit - a.Amount_Credit 'diff'
FROM _YourTable_Name a
where Account_ID = #Account_ID
And Creation_Date >= #Query_Start_Date And Creation_Date <= #Query_End_Date
)
SELECT a.Details_ID, a.Creation_Date, a.Reference_ID, a.Transaction_Kind,
a.Amount_Debit, a.Amount_Credit, SUM(b.diff) 'Balance'
FROM tempDebitCredit a, tempDebitCredit b
WHERE b.Details_ID <= a.Details_ID
GROUP BY a.Details_ID, a.Creation_Date, a.Reference_ID, a.Transaction_Kind,
a.Amount_Debit, a.Amount_Credit
Order By a.Details_ID Desc
Tested on Microsoft SQL Server

unpivot row values into multiple columns

I have the following with the following structure:
http://sqlfiddle.com/#!6/0e72e/8
CREATE TABLE Prices
(
Day date,
ProductName nVARCHAR(10),
Location nVARCHAR(10),
RegPrice1 float,
SalePrice1 float,
SalePrice2 float
)
INSERT INTO Prices VALUES ('6/24/2014', 'xbox', 'NewYork',30,20,10)
INSERT INTO Prices VALUES ('6/24/2014', 'xbox', 'London', 100,80,60)
INSERT INTO Prices VALUES ('6/24/2014', 'xbox', 'Singapore', 70,50,30)
INSERT INTO Prices VALUES ('6/24/2014', 'watch1','NewYork', 500,400,300)
INSERT INTO Prices VALUES ('6/24/2014', 'watch1','London', 1000,800,600)
INSERT INTO Prices VALUES ('6/24/2014', 'watch1','Singapore', 999,888,777)
I want to unpivot this table so it looks like:
Day Pr_Name PriceType NewYork London Singapore
2014-06-24 xbox RegPrice1 30 100 70
2014-06-24 xbox SalePrice1 20 80 50
2014-06-24 xbox SalePrice2 10 60 30
2014-06-24 watch1 RegPrice1 500 1000 999
2014-06-24 watch1 SalePrice1 400 800 888
2014-06-24 watch1 SalePrice1 300 600 777
I was able to unpivot one layer to get the NewYork column but I haven't been able to get the London and Singapore columns in place. I have tinkered with the code below to add London and Singapore but have not been successful. Do I simply keep unpivoting?
select Day, ProductName, PriceType, NewYork
from (select * from Prices ) as t
Unpivot
(
NewYork for PriceType in (RegPrice1, SalePrice1, SalePrice2)
) As unpvt
we can use CROSS APPLY to unpivot the prices and then apply PIVOT
SELECT
*
FROM
( select Day, ProductName, Location, col, value
from Prices
cross apply
(
select 'RegPrice1' , Prices.RegPrice1 union all
select 'SalePrice1', Prices.SalePrice1 union all
select 'SalePrice2', Prices.SalePrice2
) c (col, value)
) PD
PIVOT
( max(value) for Location in ([NewYork],[London],[Singapore])
)pvt