get difference between two rows and populate the difference value - sql-server

enter image description hereI have a table with the below structure.
[![enter image description here][2]][2]
I want to calculate one more column name it has "Difference". The difference should be calculated if the guid values are same and populate the difference on both rows.
After the Difference column my table should look like below
GIving more details
My table looks like below
GUID Date Quantity
0001639C-8047-45FD-8FB0-D24B906D25D0 7/21/2016 30
0001639C-8047-45FD-8FB0-D24B906D25D0 7/15/2016 20
00088951-A2F6-4405-9195-4E830912D56D 7/22/2016 40
00088951-A2F6-4405-9195-4E830912D56D 7/12/2016 20
00060D8A-F711-42BD-824F-6F9F92A02E6E 7/23/2016 2
00074492-6068-48A6-8F99-F70D7328B166 7/19/2016 15
0007E203-4BD9-4937-BFCB-6A3EBCA33448 7/15/2016 2
After Calculating the difference column it should look like below
GUID Date Quantity Difference
0001639C-8047-45FD-8FB0-D24B906D25D0 7/21/2016 30 10
0001639C-8047-45FD-8FB0-D24B906D25D0 7/15/2016 20 10
00088951-A2F6-4405-9195-4E830912D56D 7/22/2016 40 20
00088951-A2F6-4405-9195-4E830912D56D 7/12/2016 20 20
00060D8A-F711-42BD-824F-6F9F92A02E6E 7/23/2016 2 0
00074492-6068-48A6-8F99-F70D7328B166 7/19/2016 15 0
0007E203-4BD9-4937-BFCB-6A3EBCA33448 7/15/2016 2 0
The difference column should be calculated when the guid values are same ,the difference in the quantity should be performed and it should be populated in the difference column .If the guid values are not same then it should be populated with zero.

DECLARE #Table Table (GUID varchar(50), Date Date, Quantity Decimal(9,2))
Insert Into #Table (GUID,Date,Quantity) Values
('0001639C-8047-45FD-8FB0-D24B906D25D0','2016-07-21',30),
('0001639C-8047-45FD-8FB0-D24B906D25D0','2016-07-15',20),
('00088951-A2F6-4405-9195-4E830912D56D','2016-07-22',40),
('00088951-A2F6-4405-9195-4E830912D56D','2016-07-12',20),
('00060D8A-F711-42BD-824F-6F9F92A02E6E','2016-07-23',2),
('00074492-6068-48A6-8F99-F70D7328B166','2016-07-19',15),
('0007E203-4BD9-4937-BFCB-6A3EBCA33448','2016-07-15',2)
;with cteBase as (
Select *
,Difference=Quantity - Lag(Quantity) over (Partition By GUID Order By Date)
,PctChange =(100*(Lag(Quantity) over (Partition By GUID Order By Date)))/Quantity
From #Table
)
Select GUID,Date,Quantity
,Difference = sum(isnull(Difference,0)) over (Partition By GUID Order By Date Desc)
,PctChange = sum(isnull(PctChange ,0)) over (Partition By GUID Order By Date Desc)
From cteBase
Order by GUID,Date Desc
Returns
GUID Date Quantity Difference PctChange
0001639C-8047-45FD-8FB0-D24B906D25D0 2016-07-21 30.00 10.00 66.666666666666
0001639C-8047-45FD-8FB0-D24B906D25D0 2016-07-15 20.00 10.00 66.666666666666
00060D8A-F711-42BD-824F-6F9F92A02E6E 2016-07-23 2.00 0.00 0.000000000000
00074492-6068-48A6-8F99-F70D7328B166 2016-07-19 15.00 0.00 0.000000000000
0007E203-4BD9-4937-BFCB-6A3EBCA33448 2016-07-15 2.00 0.00 0.000000000000
00088951-A2F6-4405-9195-4E830912D56D 2016-07-22 40.00 20.00 50.000000000000
00088951-A2F6-4405-9195-4E830912D56D 2016-07-12 20.00 20.00 50.000000000000

DECLARE #Table Table (GUID varchar(50), Date Date, Quantity Decimal(9,2))
Insert Into #Table (GUID,Date,Quantity) Values
('0001639C-8047-45FD-8FB0-D24B906D25D0','2016-07-21',30),
('0001639C-8047-45FD-8FB0-D24B906D25D0','2016-07-15',20),
('00088951-A2F6-4405-9195-4E830912D56D','2016-07-22',40),
('00088951-A2F6-4405-9195-4E830912D56D','2016-07-12',20),
('00060D8A-F711-42BD-824F-6F9F92A02E6E','2016-07-23',2),
('00074492-6068-48A6-8F99-F70D7328B166','2016-07-19',15),
('0007E203-4BD9-4937-BFCB-6A3EBCA33448','2016-07-15',2)
;with cteBase as (
Select *
,Difference=Quantity - Lag(Quantity) over (Partition By GUID Order By Date)
From #Table
)
Select GUID,Date,Quantity
,Difference = sum(isnull(Difference,0)) over (Partition By GUID Order By Date Desc)
From cteBase
Order by GUID,Date Desc
Returns
GUID Date Quantity Difference
0001639C-8047-45FD-8FB0-D24B906D25D0 2016-07-21 30.00 10.00
0001639C-8047-45FD-8FB0-D24B906D25D0 2016-07-15 20.00 10.00
00060D8A-F711-42BD-824F-6F9F92A02E6E 2016-07-23 2.00 0.00
00074492-6068-48A6-8F99-F70D7328B166 2016-07-19 15.00 0.00
0007E203-4BD9-4937-BFCB-6A3EBCA33448 2016-07-15 2.00 0.00
00088951-A2F6-4405-9195-4E830912D56D 2016-07-22 40.00 20.00
00088951-A2F6-4405-9195-4E830912D56D 2016-07-12 20.00 20.00

Related

DENSE_RANK on two columns, where one column are distinct values and the other has duplicate

I have the following scenario where I'm struggling to understand how to apply DENSE_RANK() to get the result I want:
ID
Date
Value
1
1990-05-17
1.00
1
1991-10-12
1.00
1
1992-08-01
1.00
1
1993-07-05
0.67
1
1994-05-02
0.67
1
1995-02-01
1.00
1
1996-03-01
1.00
Based on the above data, I'm trying to identify distinct periods using the combination of the Date and Value columns, where a unique period is identified from where the Value column changes from one value to another. Here's the result I'm looking for:
ID
Date
Value
Period
1
1990-05-17
1.00
1
1
1991-10-12
1.00
1
1
1992-08-01
1.00
1
1
1993-07-05
0.67
2
1
1994-05-02
0.67
2
1
1995-02-01
1.00
3
1
1996-03-01
1.00
3
As you can see, there are 3 distinct periods. The problem I am having is that when I use DENSE_RANK(), I get one of two outcomes:
SELECT DENSE_RANK() OVER (PARTITION BY ID ORDER BY Date, Value)
ID
Date
Value
Period
1
1990-05-17
1.00
1
1
1991-10-12
1.00
2
1
1992-08-01
1.00
3
1
1993-07-05
0.67
4
1
1994-05-02
0.67
5
1
1995-02-01
1.00
6
1
1996-03-01
1.00
7
SELECT DENSE_RANK() OVER (PARTITION BY ID ORDER BY Value)
ID
Date
Value
Period
1
1990-05-17
1.00
1
1
1991-10-12
1.00
1
1
1992-08-01
1.00
1
1
1993-07-05
0.67
2
1
1994-05-02
0.67
2
1
1995-02-01
1.00
1
1
1996-03-01
1.00
1
As you can see, the problem lies with the Date column as I need that to be a cumulative period. Furthermore, the amount of periods will vary from ID to ID and there's no consistent science behind the Date column. A member could have two entries in one year for example.
You can use LAG() window function to get for each row its previous Value and with conditional aggregation with SUM() window function get the Periods:
SELECT ID, Date, Value,
SUM(CASE WHEN VALUE = prev_value THEN 0 ELSE 1 END) OVER (PARTITION BY ID ORDER BY Date) Period
FROM (
SELECT *, LAG(Value) OVER (PARTITION BY ID ORDER BY Date) prev_value
FROM tablename
) t
ORDER BY Date;
See the demo.
This is known as a gaps and island problem. One method is to use a couple of ROW_NUMBERs to put your data into groups:
WITH CTE AS(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY ID ORDER BY [date],[value])-
ROW_NUMBER() OVER (PARTITION BY ID, [value] ORDER BY [date]) AS Grp
FROM (VALUES(1,CONVERT(date,'1990-05-17'),1.00),
(1,CONVERT(date,'1991-10-12'),1.00),
(1,CONVERT(date,'1992-08-01'),1.00),
(1,CONVERT(date,'1993-07-05'),0.67),
(1,CONVERT(date,'1994-05-02'),0.67),
(1,CONVERT(date,'1995-02-01'),1.00),
(1,CONVERT(date,'1996-03-01'),1.00))V(ID,Date,Value))
SELECT ID,
Date,
Value,
DENSE_RANK() OVER (PARTITION BY ID ORDER BY Grp) AS Period
FROM CTE;

Want to have maximum price and date of each customers in customers table-

http://www.sqlcourse2.com/items_ordered.html
Above is link for table 'Customers'.
I want to have max price of orders of each customer and date of purchase
I tried like this in SQL Serer but not getting the expected answer
There shold be unique customerid in my result but m not getting it
select customerid, max(price), order_date from items_ordered group by customerid, order_date order by customerid;
This is outcome of above query while there should be unique customerid with max(price) and order date.
10101 125.00 01-Jul-1999
10101 16.00 02-Jan-2000
10101 88.70 08-Mar-2000
10101 18.30 18-Aug-1999
10101 14.75 30-Dec-1999
10101 58.00 30-Jun-1999
10298 12.50 01-Apr-2000
10298 22.00 01-Dec-1999
10298 33.00 01-Jul-1999
10298 22.38 18-Mar-2000
10298 29.00 19-Sep-1999
10299 1250.00 06-Jul-1999
10299 38.00 18-Jan-2000
10315 8.00 02-Feb-2000
10330 28.00 01-Jan-2000
10330 16.75 19-Apr-2000
10330 28.00 30-Jun-1999
10339 4.50 27-Jul-1999
10410 89.22 28-Oct-1999
10410 192.50 30-Jan-2000
10413 32.00 19-Jan-2000
10438 6.75 01-Nov-1999
10438 8.50 02-Nov-1999
10438 79.99 18-Jan-2000
10439 25.50 14-Aug-1999
10439 88.00 18-Sep-1999
10449 45.00 01-Sep-1999
10449 180.79 13-Aug-1999
10449 380.50 15-Dec-1999
10449 40.00 19-Mar-2000
10449 280.00 22-Dec-1999
10449 4.50 29-Feb-2000
First group by customerid to get the max price for each customerid and then join the results to the table:
select t.customerid, t.price, t.order_date
from items_ordered t inner join (
select customerid, max(price) maxprice
from items_ordered
group by customerid
) g on g.customerid = t.customerid and g.maxprice = t.price
order by t.customerid
Of course if there are more than 1 rows containing the max price, then all of them will be fetched.

How To Pivot table using SQL server

i creating SQL table its have three column fields
NAME TYPE Amount
RAJ 401K % 500
Kumar ROTH 600
RAJ 401K % 500
Kumar ROTH 700
Karthi 401K % 1500
RAj Roth 800
Tony DPD 8
above table i have three column Fields Name and Type finally Amount. i try convert this table like separate columns Type. in my table Raj come in table many time so i want to sum Raj all value which values come with 401K table finally its show single value. its added 401k value. Roth value seperate like this
Name 401k% Roth Amount
Raj 1000 800 1800
Kumar 0 1300 1300
Karthi 1500 0 1500.
Nimi 0 0 0 -- this is should Remove only value come with only 401k% and Roth . other value should be delete .
i want like this. i am trying to achive this using Pivot talbe i am getting Null value
select [Name],[401k%] ,[Roth%]
from DeductionHistory
PIVOT
( SUM(Amount) FOR DeductionName IN([401k%],[Roth%])
)
AS Pivottable
please any one help me . how to get value Like this
CREATE TABLE #TABLE111
([NAME] VARCHAR(6), [TYPE] VARCHAR(6), [AMOUNT] INT)
INSERT INTO #TABLE111
([NAME], [TYPE], [AMOUNT])
VALUES
('RAJ', '401K %', 500),
('KUMAR', 'ROTH', 600),
('RAJ', '401K %', 500),
('KUMAR', 'ROTH', 700),
('KARTHI', '401K %', 1500),
('RAJ', 'ROTH', 800)
SELECT NAME ,ISNULL([401K %],0) [401K %] ,ISNULL([ROTH],0) [ROTH] ,ISNULL([401K %],0)+ISNULL([ROTH],0) 'TOTAL'
FROM
(
SELECT *
FROM #TABLE111
) SRC
PIVOT
(
SUM([AMOUNT])
FOR [TYPE] IN ([401K %], [ROTH] )
) PIV
ORDER BY NAME DESC
output
NAME 401K % ROTH TOTAL
RAJ 1000 800 1800
Kumar 0 1300 1300
Karthi 1500 0 1500
--I have included DPD the query
DECLARE #DeductionHistory TABLE (NAME VARCHAR(20), [TYPE] VARCHAR(20),Amount MONEY)
INSERT INTO #DeductionHistory VALUES
('RAJ','401K%',500),
('Kumar','ROTH',600),
('RAJ','401K%',500),
('Kumar','ROTH',700),
('Karthi','401K%',1500),
('RAj','ROTH',800),
('Tony' ,'DPD', 8)
/*****Use a VTE or temp table*****/
;WITH DeductionHistory
AS(
SELECT * FROM #DeductionHistory
PIVOT
(
SUM(Amount) FOR [TYPE] IN ([401K%],[ROTH],[DPD])
) PV1
)
SELECT
[NAME]
,ISNULL([401K%],0) AS [401K%]
,ISNULL([ROTH],0) AS [ROTH]
,ISNULL([DPD],0) AS [DPD]
,ISNULL([401K%],0)+ISNULL([ROTH],0)+ISNULL([DPD],0) AS Amount
FROM DeductionHistory
OUTPUT
NAME 401K% ROTH DPD Amount
Karthi 1500.00 0.00 0.00 1500.00
Kumar 0.00 1300.00 0.00 1300.00
RAJ 1000.00 800.00 0.00 1800.00
Tony 0.00 0.00 8.00 8.00

Split a particular month into weeks and days

Suppose I took the month November.I need to display first row as shown below.The rest of the rows should be the data from database.The rows display post date and amount and if data is present on those dates,it should be shown.I also need to show the weekly totals and monthly totals of the amounts taken.This is shown for a PARTICULAR MONTH of a PARTICULAR YEAR.
I was planning to write a query for the data and implement it in Telerik via crosstab.Please give your thoughts on the same.
Input:-
POST DATE Amount($)
2013-11-01 00:00:00.000 50.00
2013-11-04 09:30:12.000 10.00
2013-11-05 11:04:00.000 20.00
2013-11-06 00:00:00.000 30.00
2013-11-07 00:00:00.000 40.00
2013-11-08 00:00:00.000 10.00
2013-11-11 00:00:00.000 10.00
2013-11-12 00:00:00.000 10.00
2013-11-15 00:00:00.000 10.00
.
.
.
The data(for the month November) should be visible like this:-
01-Nov Weekly Total 04-Nov 05-Nov 06-Nov 07-Nov 08-Nov Weekly Total 11-Nov 12-Nov 13-Nov 14-Nov 15-Nov Weekly Total 18-Nov 19-Nov 20-Nov 21-Nov 22-Nov Weekly Total 25-Nov 26-Nov 27-Nov 29-Nov Weekly Total MTD Total
50$ 50$ 10$ 20$ 30$ 40$ 10$ 110$ 10$ 10$ 10$ 30$
Thanks in advance
MSDN Date and Time Data Types and Functions (Transact-SQL)
DECLARE #TempTrans AS Table (
ID INT NOT NULL IDENTITY PRIMARY KEY
,DateTimeTrans DATETIME NOT NULL
,Amount MONEY NOT NULL
)
INSERT INTO #TempTrans (DateTimeTrans, Amount)
VALUES ('20131101', 50)
,('20131104 09:30:12',10)
,('20131104 11:04:00',15)
,('20131105',20)
,('20131106',30)
,('20131111',10)
,('20131115',80)
,('20131119',70)
,('20131123',60)
,('20111129 10:08:04',25)
SELECT *
,CASE
WHEN [weekNumber] IS NULL AND [Date] IS NULL THEN 'MTD Total'
WHEN [Date] IS NULL THEN 'Weekly Total'
ELSE CAST([Date] as varchar(30))
END as [Description]
FROM (
SELECT DATEPART(week,DateTimeTrans) as weekNumber,CAST(DateTimeTrans as date) as Date, SUM(Amount) as Amount
FROM #TempTrans
WHERE DATEPART(MONTH,DateTimeTrans) = 11
GROUP BY DATEPART(week,DateTimeTrans) ,CAST(DateTimeTrans as date)
WITH Rollup
) grp
GO

Return value's percentage of sub category in SQL

I have a query: (using a very simple example)
SELECT
ItemCategory,
ItemID,
Sales
FROM
MyTable
WHERE
CustomerID = 1
Which returns
ItemCategory | ItemID | Sales
A 0 75.00
A 1 50.00
A 2 0.00
B 3 25.00
B 4 25.00
C 5 20.00
C 6 30.00
C 7 10.00
C 8 0.00
C 9 50.00
How can I modify this query so that I receive the percentage of sales for each item grouped by ItemCategory?
That is, I would like this returned:
ItemCategory | ItemID | Sales | PercentageOfCategory
A 0 75.00 60%
A 1 50.00 40%
A 2 0.00 0%
B 3 25.00 50%
B 4 25.00 50%
C 5 20.00 20%
C 6 30.00 30%
C 7 10.00 10%
C 8 0.00 0%
C 9 50.00 50%
I tried to keep the example as trivial as possible, the actual query is pretty complex but I imagine the same logic still applies.
EDIT: I believe the server is sql server 2008
You did not mention what version of SQL server but if you have 2005+ then you could use Common Table Expressions (CTE)
;WITH RawData As
(
SELECT
ItemCategory,
ItemID,
Sales
FROM
MyTable
WHERE
CustomerID = 1
),
GroupedData As
(
SELECT
ItemCategory,
Sum(Sales) As TotalSales
FROM
RawData
GROUP BY
ItemCategory
)
SELECT
R.ItemCategory,
R.ItemID,
R.Sales,
R.Sales / G.TotalSales * 100.0 As PercentageSales
FROM
RawData R
INNER JOIN
GroupedData G
ON
R.ItemCategory = G.ItemCategory
Assuming SQL Server 2005+ for the CTE:
WITH cteCategoryTotals AS (
SELECT ItemCategory, SUM(Sales) AS TotalSales
FROM MyTable
WHERE CustomerID = 1
GROUP BY ItemCategory)
SELECT m.ItemCategory, m.ItemId, m.Sales, (m.Sales/c.TotalSales)*100.0 AS PercentageOfCategory
FROM MyTable m
INNER JOIN cteCategoryTotals
ON m.ItemCategory= c.ItemCategory
WHERE m.CustomerID = 1
You can use SUM ... OVER
SELECT
ItemCategory,
ItemID,
Sales,
100.0 * Sales /
NULLIF(SUM(Sales) OVER (PARTITION BY ItemCategory),0) AS PercentageOfCategory
FROM
MyTable
WHERE
CustomerID = 1

Resources