Pivoting/Transposing SQL Table [duplicate] - sql

This question already has answers here:
SQL Server : Columns to Rows
(7 answers)
SQL Server dynamic PIVOT query?
(9 answers)
Closed 7 years ago.
Using SQL Server 2014 Management Studio, I've been trying to find a way to convert
Year Name Col1 Col2 Col3 Col4 Col5
----------------------------------------------------
2015 ABC 0.24 0.00 0.21 0.79 0.00
2015 XYZ 0.25 0.00 0.00 0.71 0.29
to
Date Name Col Value
---------------------------
2015 ABC Col1 0.24
2015 ABC Col2 0.00
2015 ABC Col3 0.21
2015 ABC Col4 0.79
2015 ABC Col5 0.00
2015 XYZ Col1 0.25
2015 XYZ Col2 0.00
2015 XYZ Col3 0.00
2015 XYZ Col4 0.71
2015 XYZ Col5 0.29
in a dynamic fashion (i.e. it should work for any table like the first one, with n number of columns)
I've been looking around at general pivot function and doesn't seem to solve my problem.

Related

double right join query [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 months ago.
Improve this question
i have this table
declare #table table(year int, code int, import decimal(5,2))
insert into #table values
(2019,390107,10.00),
(2021,390107,175.00),
(2022,390107,102.00),
(2022,470101,101.00),
(2022,53015101,140.00)
i want to make a query that returns the import for each year and for each code contained in the following tables (return import = 0 where there is no record for a specific combination of year and code):
declare #years table (year int)
insert into #years values
(2018),
(2019),
(2020),
(2021),
(2022)
declare #codes table (code int)
insert into #codes values
(390107),
(470101),
(470103),
(471103),
(53010101),
(53015101)
i tried with somethig like that:
select
y.year,
c.code,
isnull(t.import,0)
from #table t
right join #years y on t.year = y.year
right join #codes c on t.code = c.code
the query does not return errors (is not a problem of using create Vs declare, nor a a problem with the tables name). but i don't get the result expected:
Expected Results
Having 6 codes and 5 years I expect 30 records (one for each combination of year and code) along with the corresponding import value from "#table" for that year/code combination (or 0 if the combination is not found)
year
code
import
2018
390107
0.00
2018
470101
0.00
2018
470103
0.00
2018
471103
0.00
2018
53010101
0.00
2018
53015101
0.00
2019
390107
10.00
2019
470101
0.00
2019
470103
0.00
2019
471103
0.00
2019
53010101
0.00
2019
53015101
0.00
2020
390107
0.00
2020
470101
0.00
2020
470103
0.00
2020
471103
0.00
2020
53010101
0.00
2020
53015101
0.00
2021
390107
175.00
2021
470101
0.00
2021
470103
0.00
2021
471103
0.00
2021
53010101
0.00
2021
53015101
0.00
2022
390107
102.00
2022
470101
101.00
2022
470103
0.00
2022
471103
0.00
2022
53010101
0.00
2022
53015101
140.00
You need to cross join the Codes and Years to get every combination and then use that in the outer join
SELECT Y.year,
C.code,
ISNULL(T.import, 0) AS import
FROM #years Y
CROSS JOIN #codes C
LEFT JOIN #table T
ON T.year = Y.year
AND T.code = C.code

How to use NTILE function to create two groups for two columns where one is a nested NTILE of the other?

I have financial data that I want to categorise (using NTILE()) by two columns that contain percentage values (risk, debt_to_assets). My end goal is that I want to aggregate some other column (profit) by the two categories, but that's not related to my issue at hand. The data looks something like this:
profit
risk
debt_to_assets
7000
0.10
0.20
1000
0.40
0.70
3000
0.15
0.50
4000
0.30
0.30
2000
0.20
0.60
The issue I'm trying to solve is that I want the categories to be nested such that, in addition to the population distribution being uniform, the categories of the inner quantile are consistent across the categories of the outer quantile in terms of the range that defines the categories (i.e. I want the min and max value for the inner categories (x0, y0), (x1, y0), (x2, y0), ... to all be the same or as close as possible, where the x's are the outer category and the y's are the inner category).
Ideally if I were to aggregate the columns used for the NTILE() function (using 3 inner categories and 3 outer categories for example) I'd want a table that resembles the following:
risk_cat
dta_cat
min_risk
max_risk
min_dta
max_dta
count
1
1
0.00
0.33
0.00
0.33
100
1
2
0.00
0.33
0.34
0.67
100
1
3
0.00
0.33
0.68
1.00
100
2
1
0.34
0.67
0.00
0.33
100
2
2
0.34
0.67
0.34
0.67
100
2
3
0.34
0.67
0.68
1.00
100
3
1
0.68
1.00
0.00
0.33
100
3
2
0.68
1.00
0.34
0.67
100
3
3
0.68
1.00
0.68
1.00
100
These are the solutions I've tried but they only solve part of the issue, not the whole thing:
SELECT *,
NTILE(3) OVER (
ORDER BY risk
) AS risk_cat,
NTILE(3) OVER (
ORDER BY debt_to_assets
) AS dta_cat
FROM my_table
This would result in an aggregated table like this:
risk_cat
dta_cat
min_risk
max_risk
min_dta
max_dta
count
1
1
0.00
0.33
0.00
0.33
10
1
2
0.00
0.33
0.34
0.67
55
1
3
0.00
0.33
0.68
1.00
180
2
1
0.34
0.67
0.00
0.33
135
2
2
0.34
0.67
0.34
0.67
140
2
3
0.34
0.67
0.68
1.00
100
3
1
0.68
1.00
0.00
0.33
130
3
2
0.68
1.00
0.34
0.67
110
3
3
0.68
1.00
0.68
1.00
40
The problem is that the count across the two categories isn't uniform.
WITH outer_cat AS (
SELECT *,
NTILE(3) OVER (
ORDER BY risk
) AS risk_cat
FROM my_table
)
SELECT *,
NTILE(3) OVER(
PARTITION BY risk_cat
ORDER BY debt_to_assets
) AS dta_cat
FROM outer_cat
The aggregated table for this might resemble the following:
risk_cat
dta_cat
min_risk
max_risk
min_dta
max_dta
count
1
1
0.00
0.33
0.10
0.70
100
1
2
0.00
0.33
0.71
0.90
100
1
3
0.00
0.33
0.91
1.00
100
2
1
0.34
0.67
0.05
0.35
100
2
2
0.34
0.67
0.36
0.60
100
2
3
0.34
0.67
0.61
0.90
100
3
1
0.68
1.00
0.00
0.25
100
3
2
0.68
1.00
0.26
0.50
100
3
3
0.68
1.00
0.51
0.80
100
The problem this time is that the min and max values for the inner category vary to much across the outer category.
SELECT *,
NTILE(9) OVER(
ORDER BY risk, debt_to_assets
) AS dual_cat
FROM my_table
The aggregated table for this looks something like the following:
dual_cat
min_risk
max_risk
min_dta
max_dta
count
1
0.00
0.11
0.55
1.00
100
2
0.12
0.22
0.35
1.00
100
3
0.23
0.33
0.15
1.00
100
4
0.34
0.44
0.40
1.00
100
5
0.45
0.55
0.10
1.00
100
6
0.56
0.66
0.10
0.95
100
7
0.67
0.77
0.05
1.00
100
8
0.78
0.88
0.20
1.00
100
9
0.89
1.00
0.00
1.00
100
This was just a last attempt at a solution after the previous two didn't work. This attempt didn't capture any of the behaviour that I was looking for.
Is there a solution to my problem that I'm not seeing?

SQLServer - Pivoting a table with Group

I am wondering if what I am trying to do is possible. I believe it is using the PIVOT function in TSQL but don't have enough experience with the PIVOT function to know where to start.
Basically I'm trying to take the following # table called #tmpbudgetdata (truncated for simplicity):
Account Description BudgetAmount Period
-------------------- ---------------------------------------------------------------------------------------------------- --------------------- --------------------
4001 Mood Embedded Account 0.00 1
4001 Mood Embedded Account 0.00 2
4001 Mood Embedded Account 0.00 3
4001 Mood Embedded Account 0.00 4
4001 Mood Embedded Account 0.00 5
4001 Mood Embedded Account 0.00 6
4001 Mood Embedded Account 0.00 7
4001 Mood Embedded Account 0.00 8
4001 Mood Embedded Account 0.00 9
4001 Mood Embedded Account 0.00 10
4001 Mood Embedded Account 0.00 11
4001 Mood Embedded Account 0.00 12
4003 DBS Music 0.00 1
4003 DBS Music 0.00 2
4003 DBS Music 0.00 3
4003 DBS Music 0.00 4
4003 DBS Music 0.00 5
4003 DBS Music 0.00 6
4003 DBS Music 0.00 7
4003 DBS Music 0.00 8
4003 DBS Music 0.00 9
4003 DBS Music 0.00 10
4003 DBS Music 0.00 11
4003 DBS Music 0.00 12
4010 Sales - Software 5040.00 1
4010 Sales - Software 0.00 2
4010 Sales - Software 6280.56 3
4010 Sales - Software 6947.93 4
4010 Sales - Software 4800.00 5
4010 Sales - Software 0.00 6
4010 Sales - Software 2400.00 7
4010 Sales - Software 2550.00 8
4010 Sales - Software 4800.00 9
4010 Sales - Software 2400.00 10
4010 Sales - Software 0.00 11
4010 Sales - Software 2400.00 12
4015 New Install Revenue 0.00 1
4015 New Install Revenue 0.00 2
4015 New Install Revenue 0.00 3
4015 New Install Revenue 3844.79 4
4015 New Install Revenue 0.00 5
4015 New Install Revenue 0.00 6
4015 New Install Revenue 0.00 7
4015 New Install Revenue 0.00 8
4015 New Install Revenue 0.00 9
4015 New Install Revenue 0.00 10
4015 New Install Revenue 0.00 11
4015 New Install Revenue 0.00 12
and turning it into something like this:
Account Description Period1 Period2 Period3 Period4 Period5 Period6 Period7 Period8 Period9 Period10 Period11 Period12
------- --------------- -------- ------- -------- ------ ------- ------- -------- ------ ------- -------- -------- --------
4001 Mood Enabled... 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
4003 Dbs Music 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
4010 Sales - Software 5040.00 0.00 6280.56 6947.93 4800.00 0.00 2400.00 2550.00 4800.00 2400.00 0.00 2400.00
...etc...
Basically just grouping via the Account column (the description is the same per account) and then taking the period values and pivoting them horizontally.
I know I could do it with a cursor and loop through but wondering if this is possible with a pivot or by other means.
Thanks in advance
I simple PIVOT should do the trick
Example
Select *
From (
Select [Account]
,[Description]
,Period = concat('Period',Period)
,[BudgetAmount]
From YourTable
) src
Pivot (sum([BudgetAmount]) for Period in ( [Period1],[Period2],[Period3],[Period4],[Period5],[Period6],[Period7],[Period8],[Period9],[Period10],[Period11],[Period12] ) ) pvt
Returns

How would I add both these rows together in one row with the sum of both rows

594517 2018-11-30 5.00 0.00 0.00 0.00 8.00
594517 2018-12-18 0.00 0.00 0.00 0.00 5.00
Thanks all for the reply my situation if very hard to explain with out showing the code im dealing with,Basically the fix to a huge problem would be to get many rows with different dates into one row also adding all the totals for all those row into that same one row
column is the ID, date, the rest are total for services
I have created a table called KingLove which looks like this to try out something similar to what you're explaining on my own computer:
ID date service1 service2 service3 service4 service5
----------- ---------- --------- --------- --------- --------- ---------
594517 2018-11-30 5.00 0.00 0.00 0.00 8.00
594517 2018-12-18 0.00 0.00 0.00 0.00 5.00
If I then run this query:
select max(date) as [date], sum(service1) + sum(service2) + sum(service3) + sum(service4) + sum(service5) as [sum]
from KingLove
I get the service columns summed up and the latest date as the date for the entire row. Like this:
date sum
---------- --------
2018-12-18 18.00
You could swap the max in the query for a min if you want the oldest date instead.
It is not very easy to understand what your desired outcome would be, but I hope this is what your asking.

Mssql summary row using ROLLUP

I'm trying to generate a summary row using ROLLUP grouping,
Here is my query
SELECT nic as NIC,branch_id,SUM(as_share),SUM(as_deposit) as as_deposit,SUM(as_credits) as as_credits,SUM(as_fixed) as as_fixed,SUM(as_ira) as as_ira,SUM(as_saviya) as as_saviya
FROM As_Member_Account_Details
GROUP BY nic,branch_id
WITH ROLLUP
But it give me this output,
112233 1 30.00 0.00 0.00 50.00 0.00 0.00
112233 2 20.00 0.00 0.00 0.00 0.00 0.00
112233 3 0.00 0.00 0.00 0.00 0.00 0.00
112233 NULL 50.00 0.00 0.00 50.00 0.00 0.00
NULL NULL 50.00 0.00 0.00 50.00 0.00 0.00
The row before the last row is unnecessary. Because there should be only 3 data rows + a summary row. How can I eliminate that row
Grouping sets allows more granular control when cubeing data.
SELECT nic as NIC
, branch_id,SUM(as_share)
, SUM(as_deposit) as as_deposit
, SUM(as_credits) as as_credits
, SUM(as_fixed) as as_fixed
, SUM(as_ira) as as_ira
, SUM(as_saviya) as as_saviya
FROM As_Member_Account_Details
GROUP BY GROUPING SETS ((nic,branch_id),())
WITH CTE_YourQuery AS
(
SELECT nic as NIC,branch_id,SUM(as_share),SUM(as_deposit) as as_deposit,SUM(as_credits) as as_credits,SUM(as_fixed) as as_fixed,SUM(as_ira) as as_ira,SUM(as_saviya) as as_saviya
FROM As_Member_Account_Details
GROUP BY nic,branch_id
WITH ROLLUP
)
SELECT *
FROM CTE_YourQuery
WHERE NOT (nic IS NOT NULL AND branch_id IS NULL)