Concat in select formula - snowflake - concatenation

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

Related

Sql query for multiple names in a single search engine

Can anyone help me to find out the SQL query for following scenario.
I have a search box, which I want to search multiple names separated by spaces.
for example : "David Jones" which gives me the result of David's details and Jones details.
select
emp.cid as empcid,
emp.name,
emp.employeeno,
info.employeeUniqueId,
info.agentId,
info.empBankCode,
info.accountNumber,
info.ibanAccNo
from tblemployee emp,
fk_tblUserEmployeeList f,
empinfo info
where
info.employee = emp.cid
and emp.cid = f.employeeid
and f.userId = 1
and
(
name like '%david%'
or emp.employeeno like '%david%'
or info.employeeUniqueId like '%david%'
or info.agentId like '%david%'
or info.empBankCode like '%david%'
or info.accountNumber like '%david%'
)
I want include Jones inside search box also, then how will the like condition changes>
This seems like a case for full-text search. After setting up full-text indices on your tblemployee, fk_tblUserEmployeeList, and empinfo tables, your query would look something like this:
SELECT
emp.cid AS empcid,
emp.name,
emp.employeeno,
info.employeeUniqueID,
info.agentID,
info.empBankCode,
info.accountNumber,
info.ibanAccNo
FROM dbo.tblemployee emp
INNER JOIN dbo.fk_tblUserEmployeeList f ON
f.employeeid = emp.cid
INNER JOIN dbo.empinfo info ON
info.employee = emp.cid
WHERE
f.userID = 1
AND
( FREETEXT(Emp.*, 'david jones')
OR FREETEXT(info.*, 'david jones')
)
gives you this data:
+--------+-------+------------+------------------+---------+-------------+---------------+-----------+
| empcid | name | employeeno | employeeUniqueID | agentID | empBankCode | accountNumber | ibanAccNo |
+--------+-------+------------+------------------+---------+-------------+---------------+-----------+
| 1 | David | NULL | david | david | david | david | david |
| 2 | Jones | NULL | jones | jones | jones | jones | jones |
+--------+-------+------------+------------------+---------+-------------+---------------+-----------+
Note that I changed your query to use the modern industry-standard join style.
Keep in mind that, to create a full-text index on a table, the table must have a single-column unique index. If one of your tables has a multi-column primary key, you'll have to add a column (see this question for more information).
A couple of notes about your naming conventions:
There's no need to preface table names with tbl (especially since you're not doing so consistently). There are loads of people telling you not to do this: See this answer as an example.
fk_tblUserEmployeeList is a bad table name: The prefixes fk and tbl don't add any information. What kind of information is stored in this table? I would suggest a more descriptive name (with no prefixes).
Now, if you don't want to go the route of using a full-text index, you can parse the input client-side before sending to SQL Server. You can split the search input on a space, and then construct the SQL accordingly.
declare #SearchString varchar(200)='David Jones', #Word varchar(100)
declare #Words table (Word varchar(100))
-- Parse the SearchString to extract all words
while len(#SearchString) > 0 begin
if charindex(' ', #SearchString)>0 begin
select #Word = rtrim(ltrim(substring(#SearchString,0,charindex(' ', #SearchString)))),
#SearchString = rtrim(ltrim(replace(#SearchString, #Word, '')))
end
else begin
select #Word = #SearchString,
#SearchString = ''
end
if #Word != ''
insert into #Words select #Word
end
-- Return Results
select t.*
from MyTable t
join #Words w on
' ' + t.MyColumn + ' ' like '%[^a-z]' + w.Word + '[^a-z]%'

Incorrect syntax near "case"

I have one table having data like this:
ID | Fill
---------------
1 | ####
2 | ####Y
3 | ####Y245
I want to insert the above data into another table and expecting the result table to be:
ID | Fill
----------------
1 | (Space)
2 | Y
3 | Y245
That is, when i find ####, it should be replace by space (4 space char as it has 4#)
Here is how I'm trying to do this:
insert into table1
(
id
,case
when contains(substring([fill],1,4),'####') then ' '+substring([fill],5,100)
else [fill]
end
)
select
id
,convert(char(100),[col1]+[col2]+[col3]+[col4])
from
table2
However, its showing syntax error near "case". What am I doing wrong? how can i achieve the desired result?
Just use replace()
insert into destination_table (col1)
select replace(col1, '#', ' ' ) from source_table
If # occurs, it will be replaced. If not, then the original string is used.
The case is in the field list part of the INSERT statement and is therefore not valid.
You could just use a simple replace to achieve this
INSERT INTO table1 (id, fill)
select id, replace(fill, '####', ' ') from table2

SQL: Where Clause Match Fullname with First & LastName

I have two tables, which I need to match on
"Fullname"
against
"FirstName" & "LastName"
and extract the userID from the "FirstName"/"LastName" table.
If there's a match retrieve the UserID if not Just Null
Example:
Table1 (With fullname)
|Sam Smith|
Must match with
Table2 (with first and last name)
| Sam | Smith |
And I would like to take into account if a person has three names.
(Fullname)
|Sam Samual Smith|
vs. (First & Last Name)
|Sam Samual | Smith |
Any help needed, not sure how to go around it,
As Lasse V. Karlsen suggested,
SELECT *
FROM [MainTable] M
INNER JOIN [SubTable] S
ON M.Fullname=S.Firstname + ' ' + S.Lastname; -- check if fullname is a of combination
-- firstname and lastname from other table
Replace the table names with your table names and put the fields you want in the select query as selecting all the fields could compromise the perfomance.
Try like this,
SELECT *
FROM Table1 T1
INNER JOIN Table2 T2 ON T1.FullName = T2.FirstName + ' ' + T2.LastName

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

Resources