How to keep column name after sum aggregation in SQL query - sql

I am querying SQL Server where I have multiple columns with sum aggregation. I'm wondering if there is a way to keep column name after doing sum over each of them.
I want to avoid using aliases immediately after the selected column as their numbers and names change over time.
Example of my result:
My query:
DECLARE #SQLQUERY AS NVARCHAR(MAX)
DECLARE #PivotColumns AS NVARCHAR(MAX)
DECLARE #SumColumns as NVARCHAR(MAX)
SELECT #PivotColumns = COALESCE(#PivotColumns + ',','') + QUOTENAME(description)
FROM [example-base].dbo.table
SELECT #SumColumns = 'sum('+Replace(#PivotColumns,',','),sum(')+')'
SET #SQLQUERY = N'SELECT TOP(100) Weeks, Years, Code,'+#SumColumns+ '
FROM [example-base].dbo.table
group by Weeks,Years,Code'
EXECUTE sp_executesql #SQLQUERY
Is there a way to keep column name on which is done sum?

Be aware of the potential performance issues by building a query with text. Moreover, your result may be not predictable while the number of columns can evolve between two executions.
To add an alias to your columns, you may use this statement :
DECLARE #SumColumns AS nvarchar(MAX);
SELECT #SumColumns = CONCAT(COALESCE(#PivotColumns + ',', ''), 'SUM(', QUOTENAME(description), ') AS ', QUOTENAME(description))
FROM [example-base].dbo.table

...a union..?
SET #SQLQUERY = N'
SELECT TOP(0) Weeks, Years, Code,'+#PivotColumns+ '
FROM [example-base].dbo.table
UNION ALL
SELECT TOP(100) Weeks, Years, Code,'+#SumColumns+ '
FROM [example-base].dbo.table
group by Weeks,Years,Code'

Related

sql pivot with rows join

is theres a way to join the rows based on Id and LevelReferenceNo in sql pivot function?
below is the query have been tried
declare #col nvarchar(max)
declare #squery nvarchar(max)
set #col = (select string_agg(quotename(LevelNumber), ',') from (select distinct LevelNumber from OrgLevelTable) e);
set #squery = N'select p.Id, p.LevelReferenceNo,'+ #col + ' from dbo.OrgLevelTable
PIVOT(max(LevelName) for LevelNumber IN('+#col+')) as p';
exec(#squery)
my purpose on this, why I did not use a different table on each org. levels is to handle dynamic org. levels incrementing or decrementing E.g (3 org levels become 5 or more on the upcoming months or 5 become 4 and so on)

SQL Select from an array

Is there an easy way to select from a (long) array?
I want something like this
SELECT citizenship, count(1)
FROM table
WHERE year(date) = 2018
GROUP BY citizenship
But I want all citizenship as column and all dates (from 2000 until as 2018) as rows so I can delete the where clause.
Sounds like you want to use PIVOT columns.
Heres what I think you want... ( in SQL Server)
See this article: https://www.databasejournal.com/features/mssql/converting-rows-to-columns-pivot-and-columns-to-rows-unpivot-in-sql-server.html
Applied to you that could be...
--Declare necessary variables
DECLARE #SQLQuery AS NVARCHAR(MAX)
DECLARE #PivotColumns AS NVARCHAR(MAX)
--Get unique values of pivot column
SELECT #PivotColumns= COALESCE(#PivotColumns + ',','') + QUOTENAME([citizenship])
FROM (SELECT DISTINCT [citizenship] FROM [dbo].[table]) AS PivotExample
--Create the dynamic query with all the values for
--pivot column at runtime
SET #SQLQuery =
N'SELECT [Year], ' + #PivotColumns + '
FROM (SELECT [citizenship], YEAR([Date]) AS [Year], COUNT(1) As Counter
FROM [Table] GROUP BY [citizenship], YEAR([Date])) AS A
PIVOT( SUM(Counter)
FOR [citizenship] IN (' + #PivotColumns + ')) AS P'
SELECT #SQLQuery
--Execute dynamic query
EXEC sp_executesql #SQLQuery
Adding distinct will give you list of unique citizens
SELECT distinct citizenship
FROM table
WHERE year(date) >= 2000 and year(date) <= 2018

change column names in a dynamic pivot table result

I have a tsql dynamic pivot table query that works fine although I´m not happy with the column names in the final output.
To make it work, the user has to select up to 20 fruit names from a list of 200 fruit names. Then I build the pivot table so I end up with different column names everytime the select is run.
For example:
First time the column names are: apple, orange and pear
Second time is: .orange, banana, kiwi and apple
My question is: Is there a posibility to have static names, like for example: name of the first column always "col_1", second column "col_2" etc?
The select statement is as follows:
DECLARE #idList varchar(800)
DECLARE #sql nvarchar(max)
SELECT #idList = coalesce(#idList + ', ', '') + '['+ltrim(rtrim(id_producto)) +']'
from gestor_val_pos
group by id_producto order by id_producto
SELECT #sql = 'select * from #correlaciones pivot (max (correl)
for codigo2 in (' + #IDlist + ')) AS pvt order by codigo1;'
exec sp_executeSQL #sql
sure.. just created a new variable to hold the column aliases and Row_Number to get the column number.
DECLARE #idList varchar(800)
DECLARE #idListAlias varchar(800)
DECLARE #sql nvarchar(max)
SELECT
#idList = coalesce(#idList + ', ', '') + '['+ltrim(rtrim(id_producto)) +']',
#idListAlias = coalesce(#idListAlias + ', ', '') + '['+ltrim(rtrim(id_producto)) +'] as col_' + CONVERT(VARCHAR(10), ROW_NUMBER() OVER(ORDER BY id_producto))
from gestor_val_pos
group by id_producto order by id_producto
SELECT #sql = 'select ' + #idListAlias + ' from #correlaciones pivot (max (correl)
for codigo2 in (' + #IDlist + ')) AS pvt order by codigo1;'
exec sp_executeSQL #sql
Yes, but it'll make your query significantly more complex.
You'll need to return a list of the possible column names generated from #IDList and convert that into a SELECT clause more sophisticated than your current SELECT *.
When you've got that, use some SQL string splitting code to convert the #IDList into a table of items with a position parameter. Append AS <whatever> onto the end of any you want and use the FOR XML PATH trick to flatten it back, and you've got a SELECT clause that'll do what you want. But, as I said, your code is now significantly more complicated.
As an aside - I really hope that #idList is either completely impossible for any user input to ever reach or hugely simplified from your real code for this demonstration. Otherwise you've got a big SQL injection hole right there.

Table Transform with SQL

Normally when I deal with SQL (rarely) I only use SELECT * FROM statement all the time. My primary job is working with Excel as an analysis. However, I feel my efficiency can be much improved with programming, I have started to learn some programming (VBA for Excel). Today I want to do something more advantage which is trying to transform a table using Microsoft SQL like attached picture below.
SELECT Part_Number as [Part Number], SubPart, Quantity FROM....
Bascially, the Part Number can be as many as 200, SubPart only has 3 type Sub-I, Sub-II, and Sub-III, Quantity can be anything. I need some help to transform the table as shown
Write dynamic T-Sql query as:
DECLARE #columns NVARCHAR(MAX)
,#sql NVARCHAR(MAX)
SET #columns = N''
--Get column names for entire pivoting
SELECT #columns += N', ' + QUOTENAME(SpreadCol)
FROM (select distinct Part_Number as SpreadCol
from test
) AS T
--select #columns
SET #sql = N'
SELECT SubPart, ' + STUFF(#columns, 1, 2, '') + '
FROM
(select SubPart , Part_Number as SpreadCol , Quantity
from test ) as D
PIVOT
(
sum(Quantity) FOR SpreadCol IN ('
+ STUFF(REPLACE(#columns, ', [', ',['), 1, 1, '')
+ ')
) AS Pivot1
'
--select #sql
EXEC sp_executesql #sql
Check Fiddle Demo here..
It seems you need to use Pivoting.
Refer to:
Using PIVOT and UNPIVOT
Simple Way To Use Pivot In SQL Query

Group by and aggregate functions in dynamic SQL Pivot Query

I have formulated the following dynamic SQL Query to turn an unkown number of row values (Maschine Names as nvarchar) into columns. The Row Values of the Pivoted Columns should be the sum of downtime and maintenance time (both int) for the particular Maschine.
DECLARE #columns NVARCHAR(MAX), #sql NVARCHAR(MAX);
SET #columns = N'';
SELECT #columns += N', p.' + QUOTENAME(Maschines)
FROM (SELECT Maschines FROM Rawdata AS p
GROUP BY MASCHINE) AS x;
SET #sql = N'
SELECT ' + STUFF(#columns, 1, 2, '') + '
FROM(
SELECT * from Rawdata
) AS j
PIVOT
(
SUM(maintenance) FOR Maschines IN ('
+ STUFF(REPLACE(#columns, ', p.[', ',['), 1, 1, '')
+')
) AS p;';
EXEC sp_executesql #sql;
The Query returnes the Summed up maintenance time, but once i try to include more than one column in the sum ( like Sum(maintenance+downtime) ) i get an error close to '+'.
In addition, the query returns a pivoted table, but still has the same number of rows, however i need a result that is grouped for the unkown number of columns, thus containing only one row
So unfortunately PIVOT in SQL is fairly limited in that you can only perform a single aggregation of a single column.
Your best option is instead of just doing
Select * from rawdata
as your source, include a column that pre-adds maintenance and downtime together, like
select *, maintenance + downtime as TotalTime from rawdata
and then aggregate it.