Replace NULL with some other message in pivot query - sql

I want to put 'NA' instead of null in else block.
Any way of doing that ?
select #query = coalesce(#query, '') +
N',max(case when A.[Date] = ''' +
cast(cte.startdate as nvarchar(20)) +
N''' then A.Attendance end) ' +
quotename(convert(char(6), cte.startdate,106))

You would need to do it after the max(). So I think you want:
coalesce(max(case when A.[Date] = #Date then A.Attendance end), 'N/A')
This assumes that Attendance is a string. Otherwise, you have a type error.
I should also note that embedding values in SQL strings is definitely not a good practice. You should be using parameters. In SQL Server, you would do so by using exec sp_executesql rather than just exec.

Related

SQL loop for each column in a table

Say I have a table called:
TableA
The following columns exist in the table are:
Column1, Column2, Column3
what I am trying to accomplish is to see how many records are not null.
to do this I have the following case statement:
sum(Case when Column1 is not null then 1 else 0 end)
What I want is the above case statement for every table that exists from a list provided and to be run for each columns that exists in the table.
So for the above example the case statment will run for Column1, Column2 and Column3 as there are 3 columns in that particular table etc
But I want to specfiy a list of tables to loop through executing the logic above
create procedure tab_cols (#tab nvarchar(255))
as
begin
declare #col_count nvarchar(max) = ''
,#col nvarchar(max) = ''
select #col_count += case ORDINAL_POSITION when 1 then '' else ',' end + 'count(' + QUOTENAME(COLUMN_NAME,']') + ') as ' + QUOTENAME(COLUMN_NAME,']')
,#col += case ORDINAL_POSITION when 1 then '' else ',' end + QUOTENAME(COLUMN_NAME,']')
from INFORMATION_SCHEMA.COLUMNS
where TABLE_NAME = #tab
order by ORDINAL_POSITION
declare #stmt nvarchar(max) = 'select * from (select ' + #col_count + ' from ' + #tab + ') t unpivot (val for col in (' + #col + ')) u'
exec sp_executesql #stmt
end
Wouldn't it be easy as this?
SELECT AccountID
,SUM(Total) AS SumTotal
,SUM(Profit) AS SumProfit
,SUM(Loss) AS SumLoss
FROM tblAccount
GROUP BY AccountID
If I understand this correctly you want to get the sums, but not for all rows in one go but for each accountID separately. This is what GROUP BY is for...
If ever possible try to avoid loops, cursors and other procedural approaches...
UPDATE: Generic approach for different tables
With different tables you will - probably - need exactly the statement I show above, but you'll have to generate it dynamically and use EXEC to execute it. You can go through INFORMATION_SCHEMA.COLUMNS to get the columns names...
But:
How should this script know generically, which columns should be summed up? You might head for data_type like 'decimal%' or similar...
What about the other columns and their usage in GROUP BY?
How would you want to place aliases
How do you want to continue with a table of unknown structure?
To be honest: I think, there is no real-generic-one-for-all approach for this...

My dynamic query works for when both parentsku and child sku data is present,but is not working when child is absent but parent sku is present

My dynamic query works for when both parentsku and childsku data is present,but is not working when childsku is absent but parentsku is present.This is the case it is not working ...I want it to handle both the cases...
Here is my input table
IF OBJECT_ID('tempdb..##TEMP_ParentsChild_Products') IS NOT NULL
DROP TABLE ##TEMP_ParentsChild_Products
SET #SQL = 'SELECT
a.'+#Parent_SKU+' AS ''Parent SKU''
,COUNT('+#Child_SKU+') AS ''ChildSKU_Total''
,STUFF((SELECT '','' +'+#Child_SKU+'
FROM ['+#TableName+'] b
WHERE b.'+#Parent_SKU+' = a.'+#Parent_SKU+'
FOR XML PATH('''')),1, 1, '''') AS ''ChildSKU''
INTO ##TEMP_ParentsChild_Products
FROM ['+#TableName+'] a
GROUP BY '+#Parent_SKU+'';
PRINT(#SQL)
EXEC(#SQL)
SELECT *FROM ##TEMP_ParentsChild_Products;
Here is the expected result I want:
Try this
SET #SQL = 'SELECT
a.'+#Parent_SKU+' AS ''Parent SKU''
,sum(case when '+#Child_SKU+' is null or '+#Child_SKU+' = '' then 0 else 1 end) AS ''ChildSKU_Total''
,STUFF((SELECT '','' +'+#Child_SKU+'
FROM ['+#TableName+'] b
WHERE b.'+#Parent_SKU+' = a.'+#Parent_SKU+'
AND b.'+#Child_SKU+' IS NOT NULL
FOR XML PATH('''')),1, 1, '''') AS ''ChildSKU''
INTO ##TEMP_ParentsChild_Products
FROM ['+#TableName+'] a
GROUP BY '+#Parent_SKU+'';
When you concatenate NULL into a string, the result is NULL. This applies for many other SQL operators as well.
So you could try to use ISNULL(#sku, 'null') or something along those lines.
Why must this be constructed dynamically? Dynamic SQL is rarely necessary and can pose a security risk. If I were you I would try to do this using a parameterized query/stored procedure.
there may be NULL values in the Child_SKU column, add a where condition as below to avoid null values and unnecessary comma.
SET #SQL = 'SELECT
a.'+#Parent_SKU+' AS ''Parent SKU''
,COUNT('+#Child_SKU+') AS ''ChildSKU_Total''
,STUFF((SELECT '','' +'+#Child_SKU+'
FROM ['+#TableName+'] b
WHERE b.'+#Parent_SKU+' = a.'+#Parent_SKU+'
AND b.'+#Child_SKU+' IS NOT NULL
FOR XML PATH('''')),1, 1, '''') AS ''ChildSKU''
INTO ##TEMP_ParentsChild_Products
FROM ['+#TableName+'] a
GROUP BY '+#Parent_SKU+'';

ISNULL syntax in SQL pivot

I have the following bit of code
SELECT #columns = COALESCE(#columns + ', ','') + QUOTENAME(PERIOD)
FROM (SELECT DISTINCT PERIOD FROM #p_l_summary) AS b
ORDER BY b.PERIOD
which works perfectly but generates some NULL values.
I know that I need to wrap an ISNULL around the #columns but can anyone give me the right syntax - whatever I try either generates an error or seems to have no effect.
COALESCE returns the first non-null value, so it's acting as ISNULL in your case.
So your query can return null only if PERIOD column is null. You can either filter such values out:
SELECT #columns = COALESCE(#columns + ', ','') + QUOTENAME(PERIOD)
FROM (SELECT DISTINCT PERIOD FROM #p_l_summary WHERE PERIOD IS NOT NULL) AS b
ORDER BY b.PERIOD
or use ISNULL on PERIOD:
SELECT #columns = COALESCE(#columns + ', ','') + ISNULL(QUOTENAME(PERIOD), '')
FROM (SELECT DISTINCT PERIOD FROM #p_l_summary) AS b
ORDER BY b.PERIOD
how about adding additional condition?
WHERE PERIOD IS NOT NULL

How Can we use ISNULL to all Column Names in SQL Server 2008?

I have a question
I tried to google it but looks like they don't like *
I'm using SQL Server 2008.
I have the following database table:
P_Id ProductName UnitPrice UnitsInStock UnitsOnOrder
------------------------------------------------------------------------
1 Jarlsberg 10.45 16 15
2 Mascarpone Null 23 NULL
3 Gorgonzola 15.67 9 20
If I need to replace the null with a string I know I do :
SELECT ISNULL(UnitsOnOrder,'No Data') FROM tbl
Questions
How can I use ISNULL() with multi column names ?
is it possible to use it with *
Like
SELECT ISNULL(* , 'NO data') FROM tbl
I think this will be tricky because of the datatype, you can't pass string to INT datatype so how can I fix this too
Update
Okay if i use ISNULL() with a datatype of int it will return 0
which will be a value to me , how can i pass empty string instead ?
You can use ISNULL multiple times in the same SQL statement for different columns, but you must write it separately for each column:
SELECT
ISNULL(ProductName, 'No Data') AS ProductName,
ISNULL(CAST(UnitPrice AS NVARCHAR), 'No Data') AS UnitPrice,
ISNULL(CAST(UnitsInStock AS NVARCHAR), 'No Data') AS UnitsInStock,
ISNULL(CAST(UnitsOnOrder AS NVARCHAR), 'No Data') AS UnitsOnOrder
FROM tbl
If you are building a dynamic SQL query, you could theoretically gather a list of columns in the table and generate a query with ISNULL on each one. For example:
DECLARE #SQL nvarchar(max)
SET #SQL = 'SELECT '
SELECT #SQL = #SQL + 'ISNULL(CAST([' + sc.name + '] AS NVARCHAR), ''No Data'') AS [' + sc.name + '],'
FROM sys.objects so
INNER JOIN sys.columns sc ON sc.object_id = so.object_id
WHERE so.name = 'tbl'
-- Remove the trailing comma
SELECT #SQL = LEFT(#SQL, LEN(#SQL) - 1) + ' FROM tbl'
EXEC sp_sqlexec #SQL
This code has problems when converting some column types like timestamps to an nvarchar, but it illustrates the technique.
Note that if you had another column that should be returned if a value is null, you could use the COALESCE expression like this:
SELECT COALESCE(ProductName, P_Id) AS Product...
Try this...
ISNULL (COALESCE (column1, column2), 'No Data')
You would need to include all column names though, you can't use *
COALESCE returns the first non-null value in its argument list so if they are all null it will return null

What is happening in this T-SQL code? (Concatenting the results of a SELECT statement)

I'm just starting to learn T-SQL and could use some help in understanding what's going on in a particular block of code. I modified some code in an answer I received in a previous question, and here is the code in question:
DECLARE #column_list AS varchar(max)
SELECT #column_list = COALESCE(#column_list, ',') +
'SUM(Case When Sku2=' + CONVERT(varchar, Sku2) +
' Then Quantity Else 0 End) As [' +
CONVERT(varchar, Sku2) + ' - ' +
Convert(varchar,Description) +'],'
FROM OrderDetailDeliveryReview
Inner Join InvMast on SKU2 = SKU and LocationTypeID=4
GROUP BY Sku2 , Description
ORDER BY Sku2
Set #column_list = Left(#column_list,Len(#column_list)-1)
Select #column_list
----------------------------------------
1 row is returned:
,SUM(Case When Sku2=157 Then Quantity Else 0 End) As [157 -..., SUM(Case ...
The T-SQL code does exactly what I want, which is to make a single result based on the results of a query, which will then be used in another query.
However, I can't figure out how the SELECT #column_list =... statement is putting multiple values into a single string of characters by being inside a SELECT statement. Without the assignment to #column_list, the SELECT statement would simply return multiple rows. How is it that by having the variable within the SELECT statement that the results get "flattened" down into one value? How should I read this T-SQL to properly understand what's going on?
In SQL Server:
SELECT #var = #var + col
FROM TABLE
actually concatenates the values. It's a quirks mode (and I am unable at this time to find a reference to the documentation of feature - which has been used for years in the SQL Server community). If #var is NULL at the start (i.e. an uninitialized value), then you need a COALESCE or ISNULL (and you'll often use a separator):
SELECT #var = ISNULL(#var, '') + col + '|'
FROM TABLE
or this to make a comma-separated list, and then remove only the leading comma:
SELECT #var = ISNULL(#var, '') + ',' + col
FROM TABLE
SET #var = STUFF(#var, 1, 1, '')
or (courtesy of KM, relying on NULL + ',' yielding NULL to eliminate the need for STUFF for the first item in the list):
SELECT #var = ISNULL(#var + ',', '') + col
FROM TABLE
or this to make a list with a leading, separated and trailing comma:
SELECT #var = ISNULL(#var, ',') + col + ','
FROM TABLE
You will want to look into the COALESCE function. A good article describing what is happening can be seen here.