Concatenate columns together, columns can be null - sql-server

I need to bring values together and copy it to a diffrent column.
COLUMN 1 | COLUMN 2 | COLUMN 3 | COLUMN 4
Hallo out there Hallo out there
My NULL name is My name is
I'm a rabbit I'm a rabbit
How to merge column 1, 2, 3 and copy it to column4 separated with space.
Columns can be null.

UPDATE dbo.table
SET column4 = COALESCE(column1, '')
+ COALESCE(' ' + column2, '')
+ COALESCE(' ' + column3, '');

SQL Server 2012
UPDATE table
SET Column4 = CONCAT(Column1 + ' ', Column2 + ' ', Column3)

Just use + sign
select ISNULL([COLUMN 1],'')+' ' +
isnull([COLUMN 2],'')+' ' +
isnull([COLUMN 3],'')
from your_table

Using ISNULL
UPDATE table
SET Column4 =
ISNULL(Column1+' ','') +
ISNULL(Column2+' ','') +
ISNULL(Column3,'')
Or you could consider using a calculated column.

select isnull(convert(varchar(255),[COLUMN1]),'')+' '+isnull(convert(varchar(255),[COLUMN2]),'')+' '+isnull(convert(varchar(255),[COLUMN3]),'')
from table
UPDATE table
SET COLUMN4 = isnull(convert(varchar(255),[COLUMN1]),'')+' '+isnull(convert(varchar(255),[COLUMN2]),'')+' '+isnull(convert(varchar(255),[COLUMN3]),'')
Above codes may not work depending on datatypes so you may convert it to varchar before.

update yourtable SET COlumn4= ltrim(rtrim(isnull([COLUMN 1],'') +' '+isnull([COLUMN 2],'') +' '+ isnull([COLUMN 3],'')))

Related

How to aggregate rows with "CASE WHEN" statement and build query as a string

This is my sample table:
TableName ColumnName
Sample Name
Sample MiddleName
Sample LastName
I'm trying to test the following code:
SELECT 'SELECT ' +
CASE WHEN TableName IS NOT NULL AND ColumnName IS NOT NULL THEN TableName_ColumnName
WHEN TableName IS NOT NULL AND ColumnName IS NULL THEN TableName_NULL
ELSE ISNULL(ColumnName, 'NULL')
END
+ ' FROM [TestDB].[dbo].' + TableName
FROM [TestDB].[dbo].[TestTable] WHERE TableName = 'Sample'
Here is a result I'm getting from the above, it's including the SELECT and 'FROM [TestDB].[dbo]' + TableName for each row which is not what I want:
SELECT Sample_Name FROM [TestDB].[dbo].Sample
SELECT Sample_MiddleName FROM [TestDB].[dbo].Sample
SELECT Sample_LastName FROM [TestDB].[dbo].Sample
The ideal result should look like this:
SELECT
Sample_Name
Sample_MiddleName
Sample_LastName
FROM [TestDB].[dbo].Sample
What am I missing?
If I understood correctly from your question you need a solution like this:
WITH TableNamesCTE AS
(
SELECT DISTINCT TableName
FROM TestTable
)
SELECT 'SELECT ' +
(SELECT STRING_AGG(CASE WHEN TableName IS NOT NULL AND ColumnName IS NOT NULL THEN CONCAT(TableName, '_', ColumnName)
WHEN TableName IS NOT NULL AND ColumnName IS NULL THEN CONCAT(TableName, '_NULL')
ELSE ISNULL(ColumnName, 'NULL')
END, ',')
FROM [TestTable] TT
WHERE TT.TableName = TN.TableName)
+ ' FROM [TestDB].[dbo].' + TableName
FROM TableNamesCTE TN
WHERE TN.TableName = 'Sample';
I have separated table names with CTE, so if you have 100 tables, then this query will produce 100 query strings. Once you have all tables prepared then in the second part of the query you will get aggregated all these things.
SQL Server command STRING_AGG is available from 2017 version. For more information: https://learn.microsoft.com/en-us/sql/t-sql/functions/string-agg-transact-sql?view=sql-server-ver15

Calculate the row value based on different formula

I want to calculate the cell values based on the given formula in each row.
Input record is:
Expected ouput is:
First thing is your formula is not correct. As I understand there is unique row for each sl. And to do the sum of col1 and col2 correct formula is (col1 + col2). So correct that thing first.
After that you may implement this using dynamic sql as
create table tab_sum ( id int, col1 int, col2 int, col varchar(max) )
insert into tab_sum ( id, col1, col2, col )
values ( 1, 3, 5, '(col1 + col2)' )
, ( 2, 4, 6, '(col1 + col2)' )
DECLARE #query NVARCHAR(MAX) = '';
WITH CTE_DistinctFormulas AS
(
SELECT DISTINCT col as Formula FROM tab_sum
)
SELECT #query = #query + '
UNION ALL
SELECT id, col1, col2, col, ' + Formula + ' AS CalcValue FROM tab_sum WHERE col = ''' + Formula + ''' '
FROM CTE_DistinctFormulas;
SET #query = STUFF(#query,1,12,'');
PRINT #query;
EXEC (#query);
Or if editing formula is not an option for you then you may try this, But make sure you have only one row for each id and its corresponding values otherwise it will sum all of the similar rows in one.
create table tab_sum ( id int, col1 int, col2 int, col varchar(max) )
insert into tab_sum ( id, col1, col2, col )
values ( 1, 3, 5, 'sum(col1 + col2)' )
, ( 2, 4, 6, 'sum(col1 + col2)' )
DECLARE #query NVARCHAR(MAX) = '';
WITH CTE_DistinctFormulas AS
(
SELECT DISTINCT col as Formula FROM tab_sum
)
SELECT #query = #query + '
UNION ALL
SELECT id, col1, col2, col, ' + Formula + ' AS CalcValue FROM tab_sum WHERE col = ''' + Formula + ''' group by id, col1, col2, col '
FROM CTE_DistinctFormulas;
SET #query = STUFF(#query,1,12,'');
PRINT #query;
EXEC (#query);
I think you want something like this:
select *,case when row_cal like '%1%' and row_cal like '%2%' then value1 + value2
when row_cal like '%1%' and row_cal like '%3%' then value1 + value3
end as result from YourTable
Did you have a look at the case/ when expression? See MS doc: CASE
So your query would be somthing like:
SELECT sl, audience_1, audience_2, audience_3,
CASE WHEN audience_3 > 0 THEN audience_1 + audience_3
ELSE audience_1 + audience_2
END audience_total
FROM audience
;
You did not provide the criteria, so I had to guess :-)
(I did not run the query since I had no server handy :-) )
UPDATE after comment by OP:
If you have 71 different columns for audience in the same table you have a differnt issue imho.
Then my solution would be:
split out the audience number to a detail table with sl,
audience_type and audience_count
create a audience_calc_config table with two columns calc_method and audience_type
for each different calculation and audience type add an entry to the above
table
remove formula from original table and replace with appropriate
calc_method
Then run a simple select with a JOIN, GROUP BY sl and SUM(audience)
(Of course it would be even nicer to split the audience_calc to a
master/ detail, so you can have a foreign key...)

Concat rows into 1 string

I am using SQL Server 2005 and would like to find an easier way to concat multiple rows into 1 string.
PK Column1, Column2
-- ------- -------
PK1 apple orange
PK1 pear banana
PK1 honey
PK2 apple2 orange2
PK2 pear2 banana2
PK2 honey2
Results :
PK1, apple orange pear banana honey
PK2, apple2 orange2 pear2 banana2 honey2
It is very easy to use COALESCE but it is not available in SQL Server 2005. I tried XML Path but it appends additional character to the end.
Could you please provide me some suggestion ? Thanks.
A far easier solution is to use XML PATH
SELECT #cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(a.Column1)
FROM dbo.mytbl AS a WHERE a.ColumnX = somecondition
FOR XML PATH ( '' ) , TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
SELECT #cols
Of course the WHERE clause is optional in your case. And without spoon feeding you, apply the same to your other column and concatenate them. Voila!
When your data is some blank spaces ' ' in result of for xml path you will see a at the end like ' ':
select ' ' for xml path ('');
In your case I can use this query:
select t.PK,
ltrim(rtrim(replace(
(select ' ' + isnull(ti.Column1, '') + ' ' + isnull(ti.Column2, '')
from yourTable ti
where ti.PK = t.PK
for xml path (''))
, ' ', ''))) fruits
from yourTable t
group by t.PK;
This will trap null or empty values
Declare #YourTable table (PK int,Column1 varchar(25), Column2 varchar(25))
Insert Into #YourTable values
(1,'apple','orange'),
(1,'pear','banana'),
(1,'honey', null),
(2,'apple2','orange2'),
(2,'pear2','banana2'),
(2,'honey2', null)
Select PK
,DelimString = Stuff((Select case when Column1 is null or Column1='' then '' else ' ' + replace(Column1,char(13),'') end
+case when Column2 is null or Column2='' then '' else ' ' + replace(Column2,char(13),'') end
From #YourTable
Where PK=A.PK
For XML Path('')), 1, 1, '')
From #YourTable A
Group By PK
Returns
PK DelimString
1 apple orange pear banana honey
2 apple2 orange2 pear2 banana2 honey2

Trying to pivot multiple columns in T-SQL

I have a query which dynamically generates different number of rows, with varying ID column values. I need to be able to PIVOT this into a columnar result. My current data result is below.
ID Caption FieldName FieldType
--- --------- ------------ ------------
10 Caption 1 Field Name 1 Field Type 1
11 Caption 2 Field Name 2 Field Type 2
12 Caption 3 Field Name 3 Field Type 3
20 Caption 4 Field Name 4 Field Type 4
30 Caption 5 Field Name 5 Field Type 5
My desired result is
10 11 12 20 30
-------- ---------- --------- --------- ---------
Caption 1 Caption 2 Caption 3 Caption 4 Caption 5
Field Name 1 Field Name 2 Field Name 3 Field Name 4 Field Name 5
Field Type 1 Field Type 2 Field Type 3 Field Type 4 Field Type 5
Please note that the values 10, 11, 12, 20 and 30 can change to be something else, so I understand that I need to do some dynamic sql. I want to avoid using CURSORS if possible.
Any suggestions are welcome. Please excuse the formatting
2005 Version
Declare #SQL varchar(max)
Select #SQL = stuff((Select Distinct ',' + QuoteName(ID)+'=max(case when Item='+cast(ID as varchar(25))+' then Value else null end)' From YourTable Order By 1 For XML Path('') ),1,1,'')
Select #SQL = '
Select [Seq],'+#SQL +'
From (
Select Item=A.ID,B.*
From YourTable A
Cross Apply (
Select Seq=1,Value=cast(A.Caption as varchar(max)) Union All
Select Seq=2,Value=cast(A.FieldName as varchar(max)) Union All
Select Seq=3,Value=cast(A.FieldType as varchar(max))
) B
) A
Group By Seq
Order By Seq
'
Exec(#SQL);
Returns
If you don't mind going dynamic
I'm hesitant to remove SEQ (the first column of the results). You can remove [SEQ], from the final query, but I am not sure it would maintain the proper sequence on a larger data set.
Declare #SQL varchar(max)
Select #SQL = Stuff((Select Distinct ',' + QuoteName(ID) From YourTable Order by 1 For XML Path('')),1,1,'')
Select #SQL = '
Select [Seq],' + #SQL + '
From (
Select Item=A.ID,B.*
From YourTable A
Cross Apply (
Select Seq=1,Value=cast(A.Caption as varchar(max)) Union All
Select Seq=2,Value=cast(A.FieldName as varchar(max)) Union All
Select Seq=3,Value=cast(A.FieldType as varchar(max))
) B
) A
Pivot (max(value) For Item in (' + #SQL + ') ) p'
Exec(#SQL);
Returns
EDIT - With SEQ Removed from the final Select

How to get the count (item) for week in year using SQL Server

This is a little bit hard to explain what I need to do but I will try my best and please help me. The real work is much more complicated, however, I need know how to do the basic first.
Assume I have a table called TABLE-A which ID is primary key, TYPE, And Approved Date the YEAR('Approved Date') has actually range of several years. I would like to have a SELECT STATEMENT of which it runs the COUNT(TYPE) for every week in a specified year (In this case WHERE YEAR = 2011. How could I solve this problem?
In my company, currently, we use an Excel file which just downloaded the whole table and do a lot of calculations with large number of extra columns just to get this result.
You have to use dynamic SQL and PIVOT to achieve your goal
DECLARE #cols NVARCHAR(MAX), #sql NVARCHAR(MAX)
SET #cols = STUFF((SELECT DISTINCT ',' + QUOTENAME('week ' + CONVERT(NVARCHAR(2), DATEPART(isowk, adate))
+ ' - ' + CONVERT(NVARCHAR(4), YEAR(adate)))
FROM Table1
ORDER BY 1
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'),1,1,'')
SET #sql = 'SELECT type, ' + #cols +
' FROM
(
SELECT type,
''week '' + CONVERT(NVARCHAR(2), DATEPART(isowk, adate))
+ '' - ''
+ CONVERT(NVARCHAR(4), YEAR(adate)) week,
COUNT(*) type_count
FROM table1
WHERE adate BETWEEN ''20130101'' AND ''20131231''
GROUP BY type, YEAR(adate), DATEPART(isowk, adate)
) x
PIVOT
(
MAX(type_count) FOR week IN (' + #cols + ')
) p
ORDER BY type'
EXECUTE(#sql)
Sample output:
| TYPE | WEEK 1 - 2013 | WEEK 2 - 2013 |
----------------------------------------
| A | 4 | 1 |
| B | 2 | 2 |
Here is SQLFiddle demo

Resources