Find "LIKE" duplicates in MSSQL - sql

I got a MSSQL database and there's this column with IDs.
Some are {}-wrapped around the ID and some are not.
I need to find out if there are duplicate entries like:
'{abcd}' and 'abcd' in one column.
Obviously I dont know 'abcd'...
Is there a simple way of joining the same column and searching for "LIKE" duplicates? Inner Join is not working for me...

You could do something like this:
SELECT Id
FROM TableName AS T0
WHERE EXISTS
(
SELECT 1
FROM TableName AS T1
WHERE T0.Id = '{' + T1.Id + '}'
-- Uncomment the next row if you want all duplicates (with or without brackets):
-- OR '{' + T0.Id + '}' = T1.Id
)
This will return all the records where the id is wrapped by curly brackets and has duplicate id just without the brackets.

You can also do like
CREATE TABLE T(
ID VARCHAR(25)
);
INSERT INTO T VALUES
('abc'),
('{abc}'),
('def'),
('ghi'),
('{ghi}');
SELECT *
FROM
(
SELECT TRIM(TRANSLATE(ID, '{}', ' ')) ID
FROM T
) TT
GROUP BY ID
HAVING COUNT(ID) > 1;
-- Or you can also do
SELECT *
FROM
(
SELECT REPLACE(REPLACE(ID, '{', ''), '}', '') ID
FROM T
) TT
GROUP BY ID
HAVING COUNT(ID) > 1;
Note that TRANSLATE() and TRIM() functions is available only in SQL Server 2017

Related

Create comma separated group list from rows

I need to extract a comma separated list from the following:
Return should gives something like
1 : Route#1, Route#2
2 : Route#3, Route#4
3 : Route#5
4 : Route#6
I'm struggling with the STUFF function. So far I have:SELECT STUFF( (SELECT DISTINCT ';' + T4.[Outbound Trucks] FROM #TEMP4 T4 FOR XML PATH('') ),1,1,'') AS MasterRoutes
Result gives me
any help would be really appreciated.
thanks a lof for your time
If your sql server is 2017 or more :
SELECT dorno, STRING_AGG ([Outbound Trucks], ',') as CSV
FROM #TEMP4
GROUP BY dorno
Explanation Here
In you case you can eliminate doublon to like this:
with tmp as (
select distinct dorno, [Outbound Trucks] Truck from #TEMP4
)
SELECT dorno, STRING_AGG (Truck, ',') as CSV
FROM tmp
GROUP BY dorno

Concatening in a specific order given by a number

I have a table like this:
I want to concatenate the Product name in the given Product_order by ID.
Therefore, I should get something like: CC-TC-CA for ID 1.
you can use string_agg()- it'll work sql server 2016+
select id, string_Agg(product,',') as pname
from tablename
group by id
OR you can use stuff()
SELECT id,
STUFF((SELECT ',' + product
FROM tablename AS T1
WHERE T1.id = T2.id
FOR XML PATH('')), 1, 1, '')
FROM tablename AS T2
GROUP BY id
If you can use a stored procedure instead of a single query the += operator can do what you're looking for.
DECLARE #Product_order VARCHAR(100) = '';
SELECT #Product_order += Product + '-' FROM [table] WHERE id = 1 ORDER BY Product_Order;
SELECT SUBSTRING(#Product_order, 0, LEN(#Product_order));
Update: I've learned that returning multiple rows and using in an assignment in the select clause is unsupported behavior in SQL Server.

How to avoid duplicates in the STRING_AGG function SQL Server

I was testing a query in SQL in which I need to concatenate values ​​in the form of a comma-separated list, and it works, I just have the problem of duplicate values.
This is the query:
SELECT t0.id_marcas AS CodMarca,
t0.nombremarcas AS NombreMarca,
t0.imagenmarcas,
(SELECT String_agg((t2.name), ', ')
FROM exlcartu_devcit.store_to_cuisine t1
INNER JOIN exlcartu_devcit.cuisine t2
ON t1.cuisine_id = t2.cuisine_id
WHERE store_id = (SELECT TOP 1 store_id
FROM exlcartu_devcit.store
WHERE id_marcas = t0.id_marcas
AND status = 1)) AS Descripcion,
t0.logo,
t0.imagen,
(SELECT TOP 1 preparing_time
FROM exlcartu_devcit.store
WHERE id_marcas = t0.id_marcas
AND status = 1) AS Tiempo,
t0.orden,
(SELECT TOP 1 Avg(minimum_amount)
FROM exlcartu_devcit.store_delivery_zone
WHERE id_marcas = t0.id_marcas) AS MontoMinimo
FROM exlcartu_devcit.[marcas] t0
I thought the solution could be just adding a DISTINCT to the query to avoid repeated values ​​in this way ...
(SELECT STRING_AGG(DISTINCT (t2.name), ', ') AS Descripcion
But apparently the STRING_AGG() function does not support it, any idea how to avoid repeated values?
Simplest way is just select from select, like this:
with dups as (select 1 as one union all select 1 as one)
select string_agg(one, ', ') from (select distinct one from dups) q;
vs original
with dups as (select 1 as one union all select 1 as one)
select string_agg(one, ', ') from dups;

Inner query comma separated results

My Query is:
SELECT project_type_name FROM project_type WHERE project_type_id IN
(SELECT project_type_id FROM projects WHERE project_id = 93)
Where inner query returns 1 row with 3 comma separated values. (2,3,4). But outer query returns only 1 record only for 2.
You should use find_in_set for this purpose.
SELECT project_type_name
FROM project_type
WHERE FIND_IN_SET( project_type_id, (
SELECT project_type_id
FROM projects
WHERE project_id =93
) )
You cannot treat a string of comma separated values like a list of values. In case the subquery returns always one row you can use LIKE:
SELECT project_type_name
FROM project_type
WHERE CONCAT(',', (SELECT project_type_id FROM projects WHERE project_id = 93), ',')
LIKE '%,' + project_type_id ',%'

T-SQL Comma delimited value from resultset to in clause in Subquery

I have an issue where in my data I will have a record returned where a column value will look like
-- query
Select col1 from myTable where id = 23
-- result of col1
111, 104, 34, 45
I want to feed these values to an in clause. So far I have tried:
-- Query 2 -- try 1
Select * from mytableTwo
where myfield in (
SELECT col1
from myTable where id = 23)
-- Query 2 -- try 2
Select * from mytableTwo
where myfield in (
SELECT '''' +
Replace(col1, ',', ''',''') + ''''
from myTable where id = 23)
-- query 2 test -- This works and will return data, so I verify here that data exists
Select * from mytableTwo
where myfield in ('111', '104', '34', '45')
Why aren't query 2 try 1 or 2 working?
You don't want an in clause. You want to use like:
select *
from myTableTwo t2
where exists (select 1
from myTable t
where id = 23 and
', '+t.col1+', ' like '%, '+t2.myfield+', %'
);
This uses like for the comparison in the list. It uses a subquery for the value. You could also phrase this as a join by doing:
select t2.*
from myTableTwo t2 join
myTable t
on t.id = 23 and
', '+t.col1+', ' like '%, '+t2.myfield+', %';
However, this could multiply the number of rows in the output if there is more than one row with id = 23 in myTable.
If you observe closely, Query 2 -- try 1 & Query 2 -- try 2 are considered as single value.
like this :
WHERE myfield in ('111, 104, 34, 45')
which is not same as :
WHERE myfield in ('111', '104', '34', '45')
So, If you intend to filter myTable rows from MyTableTwo, you need to extract the values of fields column data to a table variable/table valued function and filter the data.
I have created a table valued function which takes comma seperated string and returns a table value.
you can refer here T-SQL : Comma separated values to table
Final code to filter the data :
DECLARE #filteredIds VARCHAR(100)
-- Get the filter data
SELECT #filteredIds = col1
FROM myTable WHERE id = 23
-- TODO : Get the script for [dbo].[GetDelimitedStringToTable]
-- from the given link and execute before this
SELECT *
FROM mytableTwo T
CROSS APPLY [dbo].[GetDelimitedStringToTable] ( #filteredIds, ',') F
WHERE T.myfield = F.Value
Please let me know If this helps you!
I suppose col is a character type, whose result would be like like '111, 104, 34, 45'. If this is your situation, it's not the best of the world (denormalized database), but you can still relate these tables by using character operators like LIKE or CHARINDEX. The only gotcha is to convert the numeric column to character -- the default conversion between character and numeric is numeric and it will cause a conversion error.
Since #Gordon, responded using LIKE, I present a solution using CHARINDEX:
SELECT *
FROM mytableTwo tb2
WHERE EXISTS (
SELECT 'x'
FROM myTable tb1
WHERE tb1.id = 23
AND CHARINDEX(CONVERT(VARCHAR(20), tb2.myfield), tb1.col1) > 0
)