Cannot concatenate string columns - sql-server

I'd like to concatenate three columns - street, street number and city to one column "adress". The strange thing is that I cannot do it for some reason.
This is what I have tried so far:
SELECT street,
street_num,
city,
isnull(street,'') + '' + isnull(street_num,'') + '' + isnull(city,'') AS tst1, --doesnt work
concat(isnull(street,''),' ',isnull(street_num,''), ' ', isnull(city,'')) AS tst2, --doesnt work
(street_num + ' ' + street) AS tst3, --does work
(street_num + ' ' + city) AS tst4, --does work
(city + ' ' + street) AS tst5 --doesnt work
FROM [DB].[dbo].[adresses]
Note that + or concat doesnt work, it only shows the first column, street in these cases. However, if I start with street number and add street or city, it does work. But if I try to add third column, it is not shown.
If it helps, the table was pulled from Oracle by OPENQUERY and the table structure is as follows:
street VARCHAR(100), null
street_num VARCHAR(50), null
city VARCHAR(100), null
I am on MSSQL 2014.
EDIT
As asked in the comments, i cant show the data as I am dealing with addresses of our customers. Below are two dummy records plus expected result (adress) as example:
street | street_num | city | adress
--------------------------------------------------------------------
avenida pino alto | 45 | avila | avenida pino alto 45 avila
rue de abaixo | 86 | madrid | rue de abaixo 86 madrid
Furthermore, If i copy the records and do something like this, it works of course.
SELECT 'avenida pino alto' + ' ' + '45' + ' ' + 'avila'

Based on comments, it seems that your street column contains some char/data that causes problems.
I have no idea what it could be, but you can try to find out like this:
select top 10
street,
len(street) as streetCharLen,
cast(street as varbinary(500)) as streetBytes
from [DB].[dbo].[adresses]
Then compare what the different columns tell you.
Here's a quick sample:
declare #t table (
id int,
thestring varchar(50)
)
insert into #t values (1, 'test')
select thestring,
len(thestring) as slen,
cast(thestring as varbinary(100)) as sbytes
from #t
If in this sample, the slen is not 4, or the sbytes contains something that does not map back to one of the characters that I see when selecting, then something is wrong with the string.

Use convert(varchar,[exp]):
SELECT street,
street_num,
city,
isnull(convert(varchar,street),'') + '' + isnull(convert(varchar,street_num),'') + '' + isnull(convert(varchar,city),'') AS tst1
FROM [DB].[dbo].[adresses]

Try as follows.
select isnull((convert varchar(250),street),'')+isnull((convert varchar(250),[street number]),'')+
isnull((convert varchar(250),[city]),'') as 'Adress'
from .......(your query)

Related

Concat in select formula - snowflake

when I use concat in select formula I will get concat of other column too.
Example:
SELECT
firstname,
surname,
concat(firstname,' ',surname) AS fullname
FROM
employee
Source data:
| firstname | surname |
| John | Kenedy |
Output data:
| firstname | surname | fullname |
| Kenedy John | Kenedy | Kenedy Kenedy John |
Am I using concat wrog way?
Hello you have a bad syntax this must be work
SELECT CONCAT(firstname, ' ', surname) as fullname FROM employee;
Result:
+-----------------+
| fullname |
+-----------------+
| John Kenedy |
| Abraham Lincoln |
+-----------------+
You can get more info here
better still. don't use concat function. Use the operator || instead. If you use concat(), and you need to concatenate a bunch of things, it gets very ugly very quickly nesting all the concats within each other.
which do you prefer?
select concat('I ', concat('think ', concat('data ', concat('is ', 'fun '))))
-or-
select 'I ' || 'think ' || 'data ' || 'is ' || 'fun '
Your source data firstname column is not the same as your output data firstname column. If you were to run your concat function on the source data as you've presented it, then I believe you would get the results you expect.
Edit 1: Removing duplicate words from a record with SQL
Use a SPLIT_TO_TABLE table function to split each part of the concatenation to an individual row
Use QUALIFY clause to filter out duplicate words for each flattened record
Grouping by the firstname and surname, use a LISTAGG function to concatenate together each unique word using an ORDER BY clause to preserve the order of the words
CREATE OR REPLACE TEMPORARY TABLE TMP_EMPLOYEE
AS
SELECT $1 AS FIRSTNAME
,$2 AS SURNAME
FROM VALUES
('John','Kenedy')
,('Kenedy John','Kenedy')
;
WITH A AS (
SELECT E.FIRSTNAME
,E.SURNAME
,STT.SEQ
,STT.INDEX
,STT.VALUE
FROM TMP_EMPLOYEE E
,LATERAL SPLIT_TO_TABLE(FIRSTNAME || ' ' || SURNAME,' ') STT
QUALIFY ROW_NUMBER() OVER(PARTITION BY STT.SEQ,STT.VALUE ORDER BY STT.INDEX) = 1
)
SELECT A.FIRSTNAME
,A.SURNAME
,LISTAGG(A.VALUE,' ') WITHIN GROUP(ORDER BY A.INDEX) AS FULLNAME
FROM A
GROUP BY A.FIRSTNAME,A.SURNAME
;
Notes
This does not compare any two or more records to each other to find duplicates

Replace or remove data in column based on another column value

How can I replace or remove data from a column that is found in another column?
I cannot undo or prevent the way the data is being inserted, I must instead be able to determine the Address by removing all of the data found in the Place column.
The pre-calculated data populates this column as:
[Address] = '123 Main Street" + ': #McDonalds'
For Example:
+----+-------------+-----------------------------+
| ID | Place | Address |
+----+-------------+-----------------------------+
| 1 | :#McDonalds | 123 Main Street: #McDonalds |
+----+-------------+-----------------------------+
I'd like the content of [Address] to be only:
123 Main Street
One option:
Return the left part of a character string after finding the index of the ":" character.
UPDATE tbl
SET
[Address] = LEFT([Address], CASE WHEN CHARINDEX(':', [Address]) = 0 THEN
LEN([Address]) ELSE CHARINDEX(':', [Address]) - 1 END)
Another option:
UPDATE tbl
SET
[Address] = REPLACE([Address], [Place], '')
SQL Fiddle

How to concatenate the cells in a row?

There are many questions how to concatenate multiple rows into a varchar, but can you concatenate all the cells in a row into a varchar?
Example : A table with 3 columns
| Id | FirstName | LastName |
| 1 | John | Doe |
| 2 | Erik | Foo |
return the following
"1, John, Doe"
"2, Erik, Foo"
You know which table you are working on.
Note 1 : Assume that you don't know the name of the columns when you write your query.
Note 2 : I would like to avoid dynamic SQL (if possible)
Only thing I can think of is setting nocount to on outputting results to text instead of a grid using these parameters. That can be done without knowing amount of columns and avoiding Dynamic SQL.
SET NOCOUNT ON;
;WITH Test (Id, FirstName, LastName)
AS (
SELECT 1, 'John', 'Doe'
UNION ALL
SELECT 2, 'Erik', 'Foo'
)
SELECT *
FROM Test
Will return you this:
1,John,Doe
2,Erik,Foo
Here is the basic version of this. Converting this to a dynamic sql solution when the columns are unknown is going to be very tricky. You will need to use sql to dynamically generate a query similar to this. Any table that doesn't have a primary key, or a unique index would be nearly impossible because you wouldn't know what column to use as your group by. It also becomes more tricky because you don't know what datatype(s) you are working with. You would also need to be certain to add some logic to handle single quotes and NULL. This is an interesting challenge for sure. If I have time this weekend I may try to work something up for the dynamic version of this.
with Something(Id, FirstName, LastName) as
(
select 1, 'John', 'Doe' union all
select 2, 'Erik', 'Foo'
)
select STUFF((select cast(s2.Id as varchar(5)) + ', ' + s2.FirstName + ', ' + s2.LastName
from Something s2
where s2.Id = s.Id
for xml path('')), 1, 0, '') as Stuffed
from Something s
group by Id

Display two integers in one column

I have silly problem. I Have table with geometry point information and I would like to select coordinates X and Y in one column. Result of query 1
select point.STY , point.STX from vertex where id =20
is:
1 |158 | 361
However when I try to make it like:
select point.STY + ' ' + point.STX from vertex where id =20
I get summarize of 158+361 as int:
1 | 519
and the result I wan to get is:
1 | 158 361
can anyone give me a hint what am I doing wrong?
They're numeric fields, so the database presumes you want to add them mathematically. Force it to treat them as VARCHAR text fields, by using the CAST command to turn one data type into another, and it'll do as you require:
SELECT CAST(point.STY AS VARCHAR) + ' ' + CAST(point.STX AS VARCHAR)
FROM vertex
WHERE id = 20
You need to CAST the INT values as VARCHAR:
select CAST(point.STY AS VARCHAR) + ' ' + CAST(point.STX AS VARCHAR)
from vertex
where id =20

Return Multi Row DataSet as Single Row CSV without Temp Table

I'm doing some reporting against a silly database and I have to do
SELECT [DESC] as 'Description'
FROM dbo.tbl_custom_code_10 a
INNER JOIN dbo.Respondent b ON CHARINDEX(',' + a.code + ',', ',' + b.CC10) > 0
WHERE recordid = 116
Which Returns Multiple Rows
Palm
Compaq
Blackberry
Edit *
Schema is
Respondent Table (At a Glance) ...
*recordid lname fname address CC10 CC11 CC12 CC13*
116 Smith John Street 1,4,5, 1,3,4, 1,2,3, NULL
Tbl_Custom_Code10
*code desc*
0 None
1 Palm
10 Samsung
11 Treo
12 HTC
13 Nokia
14 LG
15 HP
16 Dash
Result set will always be 1 row, so John Smith: | 646-465-4566 | Has a Blackberry, Palm, Compaq | Likes: Walks on the beach, Rainbows, Saxophone
However I need to be able to use this within another query ... like
Select b.Name, c.Number, d.MulitLineCrap FROM Tables
How can I go about this, Thanks in advance ...
BTW I could also do it in LINQ if any body had any ideas ...
Here is one way to make a comma-separated list based on a query (just replace the query inside the first WITH block). Now, how that joins up with your query against b and c, I have no idea. You'll need to supply a more complete question - including specifics on how many rows come back from the second query and whether "MultilineCrap" is the same for each of those rows or if it depends on data in b/c.
;WITH x([DESC]) AS
(
SELECT d FROM (VALUES('Palm'),('Compaq'),('Blackberry')) AS x(d)
)
SELECT STUFF((SELECT ',' + [DESC]
FROM x
FOR XML PATH(''), TYPE).value(N'./text()[1]', N'varchar(max)'),1,1,'');
EDIT
Given the new requirements, perhaps this is the best way:
CREATE FUNCTION dbo.GetMultiLineCrap
(
#s VARCHAR(MAX)
)
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE #x VARCHAR(MAX) = '';
SELECT #x += ',' + [desc]
FROM dbo.tbl_custom_code_10
WHERE ',' + #s LIKE '%,' + RTRIM(code) + ',%';
RETURN (SELECT STUFF(#x, 1, 1, ''));
END
GO
SELECT r.LName, r.FName, MultilineCrap = dbo.GetMultiLineCrap(r.CC10)
FROM dbo.Respondent AS r
WHERE recordid = 116;
Please use aliases that make a little bit of sense, instead of just serially applying a, b, ,c, etc. Your queries will be easier to read, I promise.

Resources