I'm currently summing across five columns that are of money data type. The columns Amount2, Amount3, Amount4, Amount5 need to have displayed as Rows with their sum showing accordingly.
Currently the results look like this on execution of the query:
but I need the results to be displayed like in this format:
Does anyone know a way of doing this?
I did try this but not managing to get it to work:
SELECT name, amount1, column
FROM
(
select
Name,
sum(Amount1) as Amount1,
sum(Amount2) as Amount2,
sum(Amount3) as Amount3,
sum(Amount4) as Amount4,
Sum(Amount5) as Amount5
from
#temp
group by
Name
) d
UNPIVOT
(
value
for column in (Amount2,Amount3,Amount4,Amount5)
) unpiv;
I get the following error:
Msg 156, Level 15, State 1, Line 54
Incorrect syntax near the keyword 'FROM'.
Msg 102, Level 15, State 1, Line 67
Incorrect syntax near 'd'.
Sample Data
Create table #temp
(
Name varchar(10),
Amount1 money,
Amount2 money,
Amount3 money,
Amount4 money,
Amount5 money
)
insert into #temp
(
Name,
Amount1,
Amount2,
Amount3,
Amount4,
Amount5
)
SELECT
'Test',
1,
NULL,
NULL,
4,
NULL
UNION ALL
SELECT
'Test1',
1,
NULL,
NULL,
NULL,
5
UNION ALL
SELECT
'Test2',
1,
NULL,
3,
NULL,
NULL
UNION ALL
SELECT
'Test',
1,
2,
NULL,
NULL,
NULL
select
Name,
sum(Amount1) as Amount1,
sum(Amount2) as Amount2,
sum(Amount3) as Amount3,
sum(Amount4) as Amount4,
Sum(Amount5) as Amount5
from
#temp
group by
Name
drop table #temp
You can simply use UNION ALL for each type Amount
; with cte as
(
select *
from #temp
)
select
Name,
sum(Amount1) as Amount1
from
cte
group by
Name
union all
select 'Amount2', sum(Amount2) from cte
union all
select 'Amount3', sum(Amount3) from cte
union all
select 'Amount4', sum(Amount4) from cte
union all
select 'Amount5', sum(Amount5) from cte
In SQL Server, the simplest (and generally most efficient) method is apply:
select v.*
from (select Name,
sum(Amount1) as Amount1,
sum(Amount2) as Amount2,
sum(Amount3) as Amount3,
sum(Amount4) as Amount4,
sum(Amount5) as Amount5
from #temp t
group by Name
) n cross apply
(values (Name, Amount1),
('Amount2', Amount2),
('Amount3', Amount3),
('Amount4', Amount4),
('Amount5', Amount5)
) v(Name, Amount)
where v.Amount is not null;
Related
I have 2 tables: transactions and transactions_archive. Each of them has fields accountno,drcr(which has values either as C or D) and field amount. I want to get difference of sum of all 'C' in both transactions and transactions_archive and sum of all 'D' in both transactions and transactions_archive.
What query can I use to get this answer.
I tried this unsuccessfully:
select (
select accountno,drcr,sum(amount)as total from
(
select accountno,drcr,amount
from ebank.tbtransactions
where drcr='C'
union all
select accountno,drcr,amount
from ebank.tbtransactions_archive
where drcr='C'
)
)
-
(select accountno,drcr,sum(amount)as total
from (
select accountno,drcr,amount
from ebank.tbtransactions
where drcr='D'
union all
select accountno,drcr,amount
from ebank.tbtransactions_archive
where drcr='D'
)
)
group by accountno,drcr;
If I understand correctly, you want to subtract all the "D"s from the "C"s. Combine the tables using UNION ALL and use conditional aggregation:
select accountno,
sum(case when drcr = 'C' then amount else - amount end)as total
from ((select accountno, drcr, amount
from ebank.tbtransactions
) union all
(select accountno, drcr, amount
from ebank.tbtransactions_archive
)
) t
where drcr in ('D', 'C')
group by accountno;
SELECT top 1 (amount - nextamount) as diff from(
SELECT
amount,LEAD(amount, 1,0) OVER (ORDER BY YEAR(drcr)) AS nextamount FROM(
SELECT drcr, sum(amount) as amount from transactions JOIN transactions_archive on transactions.drcr and transactions_archive.drcr GROUP BY drcr))
I'm looking for some T-SQL code that will add a column called tag which will tag each row with the same number until there is a change in value within any of the columns "team", "id", "kmvid", "name", "cid" and "pid". If there is a change, use the next sequence of numbering for that row. See the expected results below as image.
You can do this with cumulative sums and lag():
select t.*,
sum(case when prev_team = team and
id = id and
kmvid = kmvid and
name = name and
prev_id = id and
prev_cid = pid and
prev_oid = cid
then 1 else 0
end) over (order by date) as Tag
from (select t.*,
lag(team) over (order by date) as prev_team,
lag(id) over (order by date) as prev_id,
lag(kmvid) over (order by date) as prev_kmvid,
lag(name) over (order by date) as prev_name,
lag(cid) over (order by date) as prev_cid,
lag(pid) over (order by date) as prev_pid
from t
) t;
You should not use a cursor for things that are better done using set-based operations.
The following will give you the desired results based on the data you took a picture of...
IF OBJECT_ID('tempdb..#TestData', 'U') IS NOT NULL
DROP TABLE #TestData;
CREATE TABLE #TestData (
CountryId CHAR(2) NOT NULL,
[Date] DATETIME NOT NULL
);
INSERT #TestData (CountryId, Date)
SELECT '99', '2004-04-30' UNION ALL
SELECT '99', '2004-07-31' UNION ALL
SELECT '99', '2004-10-31' UNION ALL
SELECT '99', '2005-01-31' UNION ALL
SELECT '99', '2005-04-30' UNION ALL
SELECT '99', '2005-07-31' UNION ALL
SELECT '99', '2005-10-31' UNION ALL
SELECT '99', '2006-01-31' UNION ALL
SELECT '99', '2006-04-30' UNION ALL
SELECT '99', '2006-07-31' UNION ALL
SELECT '99', '2006-10-31' UNION ALL
SELECT '99', '2007-01-31' UNION ALL
SELECT 'HK', '2007-04-30' UNION ALL
SELECT 'CA', '2007-07-31' UNION ALL
SELECT 'HK', '2007-10-31';
-- SELECT * FROM #TestData td;
--=======================================
WITH
cte_TagGroup AS (
SELECT
td.CountryId,
td.[Date],
TagGroup = ROW_NUMBER() OVER (ORDER BY td.Date)
- ROW_NUMBER() OVER (PARTITION BY td.CountryId ORDER BY td.Date)
- CASE WHEN td.CountryId = LAG(td.CountryId, 1, td.CountryId) OVER (ORDER BY td.CountryId, td.Date) THEN 0 ELSE 1 END
FROM
#TestData td
)
SELECT
tg.CountryId,
tg.Date,
Tag = DENSE_RANK() OVER (ORDER BY tg.TagGroup)
FROM
cte_TagGroup tg;
... That said, I suspect that the 1st 3 columns of data aren't all the same values, so you may need to add columns to the "PARTITION BY" clauses to make it fit your actual data.
HTH,
Jason
This is my sample table, I want to pivot the category column and get the sales, stock and target as rows
I want the sample output in this form as shown in the below wherein the categories are in place of columns and columns in place of row
You gotta change the name of columns for next Pivot Statement.
Like
SELECT
*
FROM
(
SELECT
Branch,
Category,
Category+'1' As Category1,
Category+'2' As Category2,
Sales,
Stock,
Target
FROM TblPivot
) AS P
-- For Sales
PIVOT
(
SUM(Sales) FOR Category IN ([Panel], [AC], [Ref])
) AS pv1
-- For Stock
PIVOT
(
SUM(Stock) FOR Category1 IN ([Panel1], [AC1], [Ref1])
) AS pv2
-- For Target
PIVOT
(
SUM(Target) FOR Category2 IN ([Panel2], [AC2], [Ref2])
) AS pv3
GO
You are ready to go now....
You can use aggregate of pv3 to sum and group by the column you need.
Sample Table :
DECLARE #Table1 TABLE
(Branch varchar(9), Category varchar(9), Sales INT,Stock INT,Target INT)
;
INSERT INTO #Table1
(Branch, Category, Sales, Stock,Target)
VALUES
( 'mumbai', 'panel', 10,4,15),
( 'mumbai', 'AC', 11,7,14),
( 'mumbai', 'Ref', 7,2,10),
( 'Delhi', 'panel',20,4,17),
( 'Delhi', 'AC', 5,2,12),
( 'Delhi', 'Ref', 10,12,22)
;
IN SQL SERVER Script :
Select BRANCH,COL,[panel],[AC],[Ref] from (
select Branch,Category,COL,VAL from #Table1
CROSS APPLY (VALUES ('Sales',Sales),
('Stock',Stock),
('Target',Target))CS (COL,VAL))T
PIVOT (MAX(VAL) FOR Category IN ([panel],[AC],[Ref]))PVT
ORDER BY Branch DESC
Try below solution
-- Applying pivoting on multiple columns
SELECT
*
FROM
(
SELECT
Category,
Sales,
FROM TblPivot
) AS P
-- For Sales
PIVOT
(
SUM(Sales) FOR Category IN ([Panel], [AC], [Ref])
) AS pv1
union all
-- For Stock
SELECT
*
FROM
(
SELECT
Category,
Stock,
FROM TblPivot
) AS P
PIVOT
(
SUM(Stock) FOR Category IN ([Panel], [AC], [Ref])
) AS pv2
union all
-- For Target
SELECT
*
FROM
(
SELECT
Category,
Target,
FROM TblPivot
) AS P
PIVOT
(
SUM(Target) FOR Category IN ([Panel], [AC], [Ref])
) AS pv3
GO
Following should work,
select * FROM
(
SELECT
Branch,
Category,
Sales,
Stock,
Target
FROM Table1
) AS P
unpivot
(
[Value] FOR [OutPut] IN (sales,stock,[target])
)unpvt
pivot
(
max([Value]) for Category in (Panel,AC,Ref)
)pvt
order by Branch Desc
From Answer1 & Answer2
(this not OP's requirement)
DECLARE #Table1 TABLE(Branch varchar(9), Category varchar(9), Sales INT,Stock INT,Target INT);
INSERT INTO #Table1
(Branch, Category, Sales, Stock,Target)
VALUES
( 'mumbai', 'panel', 10,4,15),
( 'mumbai', 'AC', 11,7,14),
( 'mumbai', 'Ref', 7,2,10),
( 'Delhi', 'panel',20,4,17),
( 'Delhi', 'AC', 5,2,12),
( 'Delhi', 'Ref', 10,12,22);
SELECT
Branch,
SUM(Panel) As PanelSales,SUM([AC]) As ACSales,SUM([Ref]) As RefSales,
SUM(Panel1) As PanelStock,SUM([AC1]) As ACStock,SUM([Ref1]) As RefStock,
SUM(Panel2) As PanelTarget,SUM([AC2]) As ACTarget,SUM([Ref2]) As RefTarget
FROM
(
SELECT
Branch,
Category,
Category+'1' As Category1,
Category+'2' As Category2,
Sales,
Stock,
Target
FROM #Table1
) AS P
-- For Sales
PIVOT
(
SUM(Sales) FOR Category IN ([Panel], [AC], [Ref])
) AS pv1
-- For Stock
PIVOT
(
SUM(Stock) FOR Category1 IN ([Panel1], [AC1], [Ref1])
) AS pv2
-- For Target
PIVOT
(
SUM(Target) FOR Category2 IN ([Panel2], [AC2], [Ref2])
) AS pv3
Group BY Branch
GO
You could first UNPIVOT the data to make it a flat table and then PIVOT to turn the categories into columns:
SELECT *
FROM SampleTable
UNPIVOT (Amount FOR Output IN (Sales, Stock, Target)) upvt
PIVOT (SUM(Amount) FOR Category IN (Panel, AC, Ref)) pvt
ORDER BY Branch, Output;
I have the following query below which works fine.
;with c as
(
select company, regionId, isnull(profit, 0) profit from MyTable
where pricedate = '2015-11-30'
)
select * from c as source pivot (max(profit ) for regionId in ([EU], [US], [JP])) as pvt
I would however like to make an adjustment to the query.
Where the regionId is equal to US I would like to multiple the profit by 0.
5 when the regionId is equal to EU I would like to multiple the profit by 0.4 & when its JP multiple the profit by 0.1.
I'm not sure about the best way of doing this? Should I do this before the pivot using a case statement or is there a better way to do it?
Try like this,
;WITH c
AS (SELECT company,
regionId,
Isnull(profit, 0) profit
FROM MyTable
WHERE pricedate = '2015-11-30')
SELECT c.company,
c.regionid,
CASE
WHEN c.regionid = 'US' THEN c.profit * 0.5
WHEN c.regionid = 'EU' THEN c.profit * 0.4
WHEN c.regionid = 'JP' THEN c.profit * 0.1
ELSE c.profit
END AS profit
FROM c
PIVOT (Max(profit )
FOR regionId IN ([EU],
[US],
[JP])) AS pvt
create table #mytable (company varchar(20), regionid varchar(10), profit money, pricedate date)
insert into
#mytable
select 'csc', 'EU', 1000,'2015-11-30'
union
select 'csc', 'US', 2000,'2015-11-30'
union
select 'csc', 'JP', 3000,'2015-11-30'
union
select 'hp', 'EU', 5000,'2015-11-30'
union
select 'hp', 'US', 4000,'2015-11-30'
union
select 'hp', 'JP', 3000,'2015-11-30'
union
select 'csc', 'EU', 1100,'2015-11-30'
union
select 'hp', 'EU', 5600,'2015-11-30'
;with c as
(
select company, regionId,
case WHEN regionid = 'US' THEN isnull(profit, 0) * 0.5
WHEN regionid = 'EU' THEN isnull(profit, 0) * 0.4
WHEN regionid = 'JP' THEN isnull(profit, 0) * 0.1
ELSE isnull(profit, 0)
END
AS profit
from #MyTable
where pricedate = '2015-11-30'
)
select * from c as source pivot (max(profit ) for regionId in ([EU], [US], [JP])) as pvt
I have a table and there are 4 fields in it, ID, Price, QTY, Ratting and Optional [Position].
I have all the records Grouped By Columns [Qty,Ratting]
I have to define the position of groupwise and store that Position into Optional column.
For better understanding I have added an image with data in table:
On the basis of QTY in Each Rating I have to Mark Top3, Bottom3 and Rest of them as remaining.
I am not getting how to do it.
Can anybody suggest me how to do it?
So far what I've tried is:
Declare #RankTable TABLE
(
ID INT,
Price Decimal (10,2),
Qty INT,
Ratting INT
)
INSERT INTO #RankTable
SELECT 1,10,15,1
UNION ALL
SELECT 2,11,11,1
UNION ALL
SELECT 3,96,10,1
UNION ALL
SELECT 4,96,8,1
UNION ALL
SELECT 5,56,7,1
UNION ALL
SELECT 6,74,5,1
UNION ALL
SELECT 7,93,4,1
UNION ALL
SELECT 8,98,2,1
UNION ALL
SELECT 9,12,1,1
UNION ALL
SELECT 10,32,80,2
UNION ALL
SELECT 11,74,68,2
UNION ALL
SELECT 12,58,57,2
UNION ALL
SELECT 13,37,43,2
UNION ALL
SELECT 14,79,32,2
UNION ALL
SELECT 15,29,28,2
UNION ALL
SELECT 16,46,17,2
UNION ALL
SELECT 17,86,13,2
UNION ALL
SELECT 19,75,110,3
UNION ALL
SELECT 20,27,108,3
UNION ALL
SELECT 21,38,104,3
UNION ALL
SELECT 22,87,100,3
UNION ALL
SELECT 23,47,89,3
DECLARE #PositionGroup VARCHAR(1)
SELECT *,ISNULL(#PositionGroup,'') AS Position FROM #RankTable
You can try this:
SELECT ID
,Price
,Qty
,Ratting
,CASE WHEN RowID >= 1 AND RowID <= 3
THEN 0
ELSE CASE WHEN RowID > Total - 3 THEN 1 ELSE 2 END END AS Position
FROM (SELECT ID
,Price
,Qty
,Ratting
,COUNT(*) OVER(PARTITION BY Ratting) AS Total
,ROW_NUMBER() OVER(PARTITION BY Ratting ORDER BY Qty DESC) AS RowID
,ISNULL(#PositionGroup,'') AS Position
FROM #RankTable) AS T
Use Window Function. Try this.
;WITH cte
AS (SELECT *,
Row_number()OVER(partition BY rating ORDER BY id) rn,
count(id)OVER(partition BY rating) mx
FROM #RankTable)
SELECT ID,
Price,
Qty,
Rating,
mx - rn,
CASE WHEN rn IN ( 1, 2, 3 ) THEN 0
WHEN mx - rn IN( 0, 1, 2 ) THEN 1
ELSE 2
END position
FROM cte
try this as well.
;WITH cte AS
(
SELECT MAX(Row) [Max],
MIN(Row) [Min],
LU.Ratting
FROM (
SELECT *,
ROW_NUMBER() OVER(PARTITION BY Ratting ORDER BY Qty DESC) Row
FROM #RankTable)LU
GROUP BY LU.Ratting
)
SELECT ID,
R.Price,
R.Qty,
cte.Ratting,
CASE WHEN (Row - Min) <= 2 THEN 0 WHEN (Max - Row) <= 2 THEN 1 ELSE 2 END Position
FROM cte
JOIN (
SELECT Ratting,
ID,
Price,
Qty,
ROW_NUMBER() OVER(PARTITION BY Ratting ORDER BY Qty DESC) [Row]
FROM #RankTable
) R ON R.Ratting = cte.Ratting
Result: