How to filter the String based on , and delete the duplicates - sql

Let's Assume I have DataTable in Ms sql that represents simple matrix
Existing Table
ids_cloumn
========================
RX ,BX , AS , RX ,BX , AS
XR ,Xs , AS
XR ,Xs , AS,XR ,Xs , AS
RX ,BX , AS ,
RX ,BX , AS ,
I want to filter the duplicated data in string and data is separated by ' , '
ids_column
========================
RX ,BX , AS
XR ,Xs , AS
XR ,Xs , AS
RX ,BX , AS ,
RX ,BX , AS ,
right now i am using this But this approach is unsuccessful
declare #i int
declare #c char
declare #rst varchar(8000)
set #i=1
set #rst=substring(‘aaassrt’,1,1)
set #c=”
while #i<=len(‘aaassrt’)
begin
set #c=substring(‘aaassrt’,#i,1)
if charindex( #c,#rst,1)=0
set #rst=#rst+#c
set #i=#i+1
end
select #rst

i hope this will help you xQuery but i am not able to remove last comma of string :( another thing for my below query you have to keep specific space between character
declare #temp table (Id int,val nvarchar(33))
insert into #temp values (1,'RX ,BX ,AS ,RX ,BX ,AS')
insert into #temp values (2,'XR ,Xs ,AS ')
insert into #temp values (3,'XR ,Xs ,AS ,XR ,Xs ,AS')
insert into #temp values (4,'RX ,BX ,AS ,')
insert into #temp values (5,'RX ,BX ,AS ,')
select Id,
REPLACE(cast(cast('<d>'+ replace(LTRIM(RTRIM(val)), ' ,','</d><d>')+'</d>' as xml)
.query('distinct-values(/d)') as varchar), ' ', ' ,')AS [val]
from #temp;
RESULT

This is one way on doing it:
declare #data table(ids nvarchar(100))
insert into #data(ids) values
('1 , 2 , 4 , 23 , 1 , 2 , 4 , 23 ,')
, ('1 , 3 , 4 , 3 , 4 ')
, ('2 , 3 , 6 ,')
, ('3 , 5 , 8 , 3 , 5 ')
, ('1 , 7 , 9 ')
Select distinct xml.ids, LTRIM(RTRIM(x.id.value('.', 'varchar(5)'))) as id
From (
Select ids
, CAST('<x>'+REPLACE(ids, ',', '</x><x>') + '</x>' as xml) as data
From #data
) as xml
Cross Apply data.nodes('x') as x(id)
Where LTRIM(RTRIM(x.id.value('.', 'varchar(5)'))) <> ''
Like it has been said by everyone else, you should not store comma separated value in one single column.
You should record it in rows in another table and join it to your main table.

Related

split data delimited by character

I really would appreciate someone's help
I`m a newbie in all of this SQL-SSIS stuff
I have the following table in SQL:
And I need to create a table with columns that contain the AreaPath column and parsed by the delimiter \
Meaning my final goal is this:
Couple of important things:
The original table is constantly changing (every 10 minutes)
I have SQL 2014
I can use SSIS to do so (I prefer to, than SQL)
Any help would be appreciated
Thanks!
If you use the string delimit function from this link and use PIVOT
Then the following works
DECLARE #Delim NVARCHAR(32) = '\';
DECLARE #t TABLE ( AreaSK INT, AreaName NVARCHAR(100), AreaPath NVARCHAR(100))
INSERT INTO #t
(AreaSK, AreaName, AreaPath)
VALUES
(12188, 'Kryptonite', '\Kryptonite'),
(12191, 'SL_A', '\Kryptonite\SL_A'),
(12192, 'P_Bender', '\Kryptonite\SL_A\ART_APL\PG_Apollo\P_Bender'),
(12194, 'PG_Edison', '\Kryptonite\SL_A\ART_APL\PG_Apollo\P_Bender\test\PG_Edison')
SELECT PVT.AreaSK
, PVT.AreaName
, PVT.TeamProject
, PVT.AL
, PVT.ART
, PVT.PG
, PVT.P
, PVT.T
FROM
(
SELECT
T.AreaSK
, T.AreaName
, CASE
WHEN rn = 1 THEN 'TeamProject'
WHEN rn = 2 THEN 'AL'
WHEN rn = 3 THEN 'ART'
WHEN rn = 4 THEN 'PG'
WHEN rn = 5 THEN 'P'
WHEN rn = 6 THEN 'T'
END 'Headings'
, [Value]
FROM
(
SELECT T.AreaSK
, T.AreaName
, T.AreaPath
, AreaPath2 = RIGHT(T.AreaPath, LEN(T.AreaPath) - 1) --remove first '\'
FROM #t T
) T
CROSS APPLY
dbo.FN_SplitString_AB(T.AreaPath2, #Delim)
) T
PIVOT
(
MAX(Value)
FOR Headings IN ([T],[P],[PG],[ART],[AL],[TeamProject])
) PVT
Output

How to create a view with 14000 Columns in it?

I have two tables
Shop
Item.
and a third table which shows availability of Item in a shop with cost of the item in that shop.
Shop_Item_Mapping.
Some sample data of Item would be (1, Candy) where 1 is id and Candy is name of the Item.
(2 , Chocolate)
(3 , Chair)
(4 , Mobile)
(5 , Bulb)
Some sample data of Shop table would be
(1 , Address Of Shop)
(2 , Address Of Shop)
(3 , Address of the shop)
Now my mapping table shows me that which Item is available in which shop and at what cost.
Shop_Item_Mapping ( Shop_id , Item_Id , Cost of Item).
So my mapping tables have these entries
SID , IID , Cost
(1 , 1, 5)
(1 , 2 ,10)
(1 ,4 ,2300)
(2 ,3 ,50)
(2 , 5 ,10)
(3 , 1 , 4)
(3 , 2 , 5 )
(3 , 4 , 2500 )
(3 , 5 , 12 )
Now I have a query that I want all those shops which have both Mobile ( id = 4 ) and Chocolates(id = 2) with mobile price < 3000 and chocolate price less than 7.
I am trying to make a view where I will have data like this
Shop_ID , I1 , I2 , I3 , I4 , I5 where I1 , I2 , I3 , I4 , I5 are the id of Items and value of these will be cost of the item in that shop.
So my view would be
(1 , 5 , 10 , NULL , 2300 , NULL )
(2 , NULL , NULL , 50 , NULL , 10)
(3 , 4 , 5 , NULL , 2500 , 12 ).
I am able to do so when my items are less. But IF I have more than 15000 Items in my repository, Can I create a view with these many columns ?
Seriously? 14,000 columns in a view? You have a serious design issue here. However if you want to have a go, try this dynamic pivot query. It works with the limited data you have provided:
DECLARE #ColumnList VARCHAR (MAX)
DECLARE #SQL VARCHAR(MAX)
-- Create a list of distinct Item IDs which will become column headers
SELECT #ColumnList = COALESCE(#ColumnList + ', ','') + 'ItemID' + CAST(I.ItemID AS VARCHAR(12)) FROM (SELECT DISTINCT ItemID FROM Item) I
SET #SQL = '
SELECT
ShopID, ' + #ColumnList + '
FROM
(
SELECT
s.ShopID,
ItemID = ''ItemID'' + Cast(i.ItemID as varchar(12)),
sim.ItemCost
FROM
dbo.Shop_Item_Mapping AS sim
JOIN dbo.Shop AS s ON sim.ShopID = s.ShopID
JOIN dbo.Item AS i ON SIM.ItemID = i.ItemID
) T
PIVOT
(
MIN(ItemCost)
FOR T.ItemID IN (' + #ColumnList + ')
) AS PVT'
exec (#SQL)
Edited field names as per updated question.

SQL Pivot Issue

If you could please help with this. The code generates an error:
Msg 8156, Level 16, State 1, Line 236
The column 'Classification_Value_Id' was specified multiple times for 'piv1'.
I am doing this on SQL Server. The steps for the code is as follows:
1. Unpivot the data from the source table DB.[dbo].[Classification] into one column
2. Join this unpivoted data to a table called DB.dbo.[Classification_Value] to return/add the column 'cv.Classification_Name' to the data set
3. Pivot this dataset (This is the part returning the error)
CODE:
SELECT
activityCode
, actjvPartnerRef
, actMonth
, actSalesChannel
, addCBPCharge
, agentId
, appType
, areaCode
--SELECT
--polRef,[Arrangement_Id],UnpivotedData.Classification_Value_Id,UnpivotedData.Classification_Scheme_Id,ColValues, ColNames,cv.Classification_Name
FROM
(
SELECT top 10
[polRef]
, [Arrangement_Id]
, [Classification_Scheme_Id]
, [Classification_Value_Id]
-- ,[Arrangement_Classification_Type_Id]
-- ,[Effective_TimeStamp]
-- ,[End_date]
, CAST((ISNULL([character_measure],'')) AS NVARCHAR(MAX)) AS character_measure
, CAST((ISNULL([datetime_measure],'')) AS NVARCHAR(MAX)) AS datetime_measure
, CAST([decimal_measure] AS NVARCHAR(MAX)) AS decimal_measure
, CAST((ISNULL([integer_measure],'')) AS NVARCHAR(MAX)) AS integer_measure
, CAST((ISNULL([logical_measure],'')) AS NVARCHAR(MAX)) AS logical_measure
, CAST((ISNULL([charmax_measure],'')) AS NVARCHAR(MAX)) AS charmax_measure
, CAST((ISNULL([long_measure],'')) AS NVARCHAR(MAX)) AS long_measure
FROM DB.[dbo].[Classification]
) AS SrcDataConverted
UNPIVOT
(
ColValues FOR ColNames IN
(
character_measure
, datetime_measure
, decimal_measure
, integer_measure
, logical_measure
, charmax_measure
, long_measure
)
) AS UnpivotedData
LEFT JOIN DB.dbo.[Classification_Value] cv
ON cv.[Classification_Scheme_Id] = UnpivotedData.[Classification_Scheme_Id]
AND cv.Classification_Value_Id = UnpivotedData.Classification_Value_Id
PIVOT
(MAX(ColValues) for Classification_Name in (
activityCode
, actjvPartnerRef
, actMonth
, actSalesChannel
, addCBPCharge
, agentId
, appType
, areaCode
)) AS piv1;
Any help would be much appreciated
Thank you
StuarLC:
An additional derived table needs to wrap the results of the UNPIVOT before commencing the re-PIVOT, as the join introduces a duplicated Classification_Value_Id and Classification_Scheme_id, which is needed for the join.
select
activityCode
, actjvPartnerRef
, actMonth
, actSalesChannel
, addCBPCharge
, agentId
, appType
, areaCode
from (
SELECT polRef
, [Arrangement_Id]
, UnpivotedData.Classification_Value_Id
, UnpivotedData.Classification_Scheme_Id
, ColValues
, ColNames
, Classification_Name
FROM (
SELECT [polRef]
, [Arrangement_Id]
, [Classification_Scheme_Id]
, [Classification_Value_Id]
, CAST((ISNULL([character_measure],'')) AS NVARCHAR(MAX)) AS character_measure
, CAST((ISNULL([datetime_measure],'')) AS NVARCHAR(MAX)) AS datetime_measure
, CAST([decimal_measure] AS NVARCHAR(MAX)) AS decimal_measure
, CAST((ISNULL([integer_measure],'')) AS NVARCHAR(MAX)) AS integer_measure
, CAST((ISNULL([logical_measure],'')) AS NVARCHAR(MAX)) AS logical_measure
, CAST((ISNULL([charmax_measure],'')) AS NVARCHAR(MAX)) AS charmax_measure
, CAST((ISNULL([long_measure],'')) AS NVARCHAR(MAX)) AS long_measure
FROM DB.[dbo].[Classification]
) AS SrcDataConverted
UNPIVOT
(
ColValues FOR ColNames IN
(
character_measure
, datetime_measure
, decimal_measure
, integer_measure
, logical_measure
, charmax_measure
, long_measure
)
) AS UnpivotedData
LEFT JOIN
DB.dbo.[Classification_Value] cv
ON cv.[Classification_Scheme_Id] = UnpivotedData.[Classification_Scheme_Id]
AND cv.Classification_Value_Id = UnpivotedData.Classification_Value_Id
) as src
PIVOT
(
MAX(ColValues) for Classification_Name in (
activityCode
, actjvPartnerRef
, actMonth
, actSalesChannel
, addCBPCharge
, agentId
, appType
, areaCode
)
) AS piv1;

T-SQL - Compare multiple Columns in the same row

I need to compare multiple columns from then same row in a table
For example
I have on a row
1 | name | surname | phone | nameWeb | surnameWeb | phoneWeb ...
and I need to compare data from DB and data from Web [....Web] columns
something like this
name | nameWeb
surname | surnameWeb
phone | phoneWeb
...
I did this with temporary tables and multiple inserts but I need an optimized solusition because I have a lot of columns
my code
SELECT
-- Contatto
c.id ,
-- Ditta
d.nome 'nomeDitta' ,
d.filiale ,
d.webNome webNomeDitta ,
d.webDescrizione webDescrizione ,
-- Persona
p.nome Nome ,
p.cognome Cognome ,
p.email ,
p.telefono ,
p.fax ,
p.webNome ,
p.webCognome ,
p.webEmail ,
p.webTelefono ,
p.webFax ,
p.webNoteAggiuntive ,
p.canali ,
-- Indirizzo
i.indirizzo1 ,
i.indirizzo2 ,
i.cap ,
i.localita ,
i.webIndirizzo1 ,
i.webIndirizzo2 ,
i.webCap ,
i.webLocalita ,
i.webNome 'NomeInd' ,
-- Nazione
n.stato 'Nazione' ,
n2.stato 'webNazione' ,
-- Lingua
L.nome 'webLingua'
INTO #webCont
FROM dbo.contatto c ...
WHERE c.id = #idContatto
DECLARE #result TABLE ( ColumnName NVARCHAR(100) ,
DB NVARCHAR(100) ,
Web NVARCHAR(100) ,
hasData BIT)
INSERT INTO #result SELECT 'Nome Ditta' , nomeDitta , webNomeDitta , #hasData FROM #webCont
INSERT INTO #result SELECT 'Nome' , Nome , webNome , #hasData FROM #webCont
INSERT INTO #result SELECT 'Cognome' , Cognome , webCognome , #hasData FROM #webCont
INSERT INTO #result SELECT 'eMail' , email , webEmail , #hasData FROM #webCont
INSERT INTO #result SELECT 'Telefono' , telefono , webTelefono , #hasData FROM #webCont
INSERT INTO #result SELECT 'Fax' , fax , webFax , #hasData FROM #webCont
INSERT INTO #result SELECT 'Indirizzo 1' , indirizzo1 , webIndirizzo1 , #hasData FROM #webCont
INSERT INTO #result SELECT 'Indirizzo 2' , indirizzo2 , webIndirizzo2 , #hasData FROM #webCont
INSERT INTO #result SELECT 'Cap' , cap , webCap , #hasData FROM #webCont
INSERT INTO #result SELECT 'Localita' , localita , webLocalita , #hasData FROM #webCont
INSERT INTO #result SELECT 'Nazione' , Nazione , webNazione , #hasData FROM #webCont
Thank you ,
Marian
Ok, I tried to compile a fairly detailed example for you. What this will do, is build up a dynamic query by:
Finding all columns in the specific table NOT ending in "Web"
Finding all columns in the specific table that DO end in "Web"
Join those two result-sets together and construct a test to measure equality
Use the combined result-set to construct a dynamic query that will execute and perform the necessary matches across all tables that might have a "%Web" counterpart.
Obviously, this solution won't work 100% for you, but might guide you into the solution you need. So, without any further ado, I present THE CODE:
DECLARE
#SQL nvarchar(max)
, #TableName nvarchar(max)
SET #TableName = 'Test'
SET #SQL = 'SELECT '
;WITH NonWeb AS
(
SELECT
[COLUMN_NAME] as [NonWebColumn]
FROM INFORMATION_SCHEMA.COLUMNS
WHERE
[TABLE_NAME] = #TableName
AND [COLUMN_NAME] NOT LIKE '%Web'
),
Web AS
(
SELECT
'[' + C.[COLUMN_NAME] + ']' as [WebColumn]
, '[' + NonWeb.[NonWebColumn] + ']' as [NonWebColumn]
, 'CASE WHEN [' + C.[COLUMN_NAME] + '] = [' + NonWeb.[NonWebColumn] + '] THEN ''Equal'' ELSE ''Not Equal'' END as [' + NonWeb.[NonWebColumn] + 'Match]' as [Match]
FROM INFORMATION_SCHEMA.COLUMNS C
INNER JOIN NonWeb ON
REPLACE(C.[COLUMN_NAME],'Web','') = NonWeb.[NonWebColumn]
WHERE
[TABLE_NAME] = #TableName
AND [COLUMN_NAME] LIKE '%Web'
)
SELECT #SQL = 'SELECT ' + STUFF
(
(
SELECT
', ' + [NonWebColumn] + ', ' + [WebColumn] + ', ' + [Match]
FROM Web
FOR XML PATH('')
)
, 1
, 2
, ''
) + ' FROM ' + #TableName
EXEC sp_ExecuteSql #SQL
You can just change the value of the #TableName variable (which gets set at the beginning) to whatever the name of your specific table is and test it out. The assumption here is of course that there are columns that end in "Web" in that specific table...
I think you don't need #result table, you can use UNION instead. Also you should do analysis of your query we don't see in your sample FROM dbo.contatto c ... Here described how to do this. Might be you also don't need #webCont, but it really depend. Might be you should consider using Indexed Views, they slows operations but can be used for lookup tables.

Getting MAX Value of a Field for INSERT Statement

I am trying to insert a new record in a small settings table and I would like to get the MAX value of the DisplayOrder field and add 10 to it. I get errors with the MAX function in the value of the insert.
INSERT INTO tMrMenu
([ParentId]
,[DisplayOrder]
,[ItemName]
,[ItemDescription]
,[ItemURL]
,[ItemImage]
,[CreateDate]
,[CreateUser]
,[LastUpdateDate]
,[LastUpdateUser]
,[module]
,[isactive])
SELECT
( 1
, (SELECT MAX(DisplayOrder) + 10 FROM tMrMenu)
, 'EDM Summary Text'
, 'EDM Summary Text'
, '/Offline/Reports/EdmSummaryText'
, 'cli.gif'
, GETDATE()
, 'Garry.Bargsley'
, GETDATE()
, 'Garry.Bargsley'
, 'MR'
, 1)
You have extra parenthesis:
INSERT INTO tMrMenu
([ParentId]
,[DisplayOrder]
,[ItemName]
,[ItemDescription]
,[ItemURL]
,[ItemImage]
,[CreateDate]
,[CreateUser]
,[LastUpdateDate]
,[LastUpdateUser]
,[module]
,[isactive])
SELECT
1
, (SELECT MAX(DisplayOrder) + 10 FROM tMrMenu)
, 'EDM Summary Text'
, 'EDM Summary Text'
, '/Offline/Reports/EdmSummaryText'
, 'cli.gif'
, GETDATE()
, 'Garry.Bargsley'
, GETDATE()
, 'Garry.Bargsley'
, 'MR'
, 1
Declare #max int
SET #max = (SELECT MAX...)
INSERT INTO tMrMenu...
SELECT
...
#max,
...
INSERT INTO tMrMenu
([ParentId]
,[DisplayOrder]
,[ItemName]
,[ItemDescription]
,[ItemURL]
,[ItemImage]
,[CreateDate]
,[CreateUser]
,[LastUpdateDate]
,[LastUpdateUser]
,[module]
,[isactive])
SELECT MAX(DisplayOrder) + 10
, 'EDM Summary Text'
, 'EDM Summary Text'
, '/Offline/Reports/EdmSummaryText'
, 'cli.gif'
, GETDATE()
, 'Garry.Bargsley'
, GETDATE()
, 'Garry.Bargsley'
, 'MR'
, 1
FROM tMrMenu