Click here to Skip to main content
15,891,513 members
Please Sign up or sign in to vote.
2.50/5 (2 votes)
See more:
Hi everybody!

I'm almost newbie with sql.. but trying build a query.. too complicated for my knowledge:

Issue is concering handling colors in different languages

SQL
I have "COLORS" table with colors with following fields
ID	EN	DE	FR	PT
1	white	weiss	blanc	branco
2	black	schwarz	noir	preto
3	red	rot	rouge	vermelho

.....

then I have "ITEMS" table with products that, among others, has a "colors" field.. something lime this

SQL
ID	ItemID	Model	Colors
1	MT002	S9500	black#white#red
2 	MZ412	W8	black#red
3	MZ415	W8s	black#white
4       MZ499   N9500   red


given the following parameters

Language="FR"
SelectedProduct="'MZ412','MZ415'"

with a query , I want select the models of the selected product with relative colors in selected language; ie: I expect something like this as output:

Model CLRS
W8 blanc#rouge
W8s noir#blanc


I did this:

SQL
SELECT Items.Model, 
(SELECT fr  FROM Colors where colors.EN in (case when charindex('#',items.Colors) = 0 then items.colors else left(items.Colors,charindex('#',items.Colors)-1)end )) 
+'#'+(SELECT fr  FROM Colors where colors.EN in (case when charindex('#',items.Colors) = 0 then items.colors else right(items.Colors,charindex('#',reverse(items.Colors))-1)end )) as CLRS 
FROM Items WHERE Items.ID IN ('MZ412','MZ415')


that works.. but only if have 1 or 2 colors..
can fix if have no color.. but what about if have 3 or more colors?

can give an idea of the path to follow?

Thanks

Jan
Posted
Updated 30-Sep-13 0:02am
v4

hi...

check the below SQL Logic... you can use one UDF for Spit the values....
SQL
-- split function
create function fnsplitstring(@str nvarchar(max),@sep nvarchar(max))
returns table
as
return
with a as(
	select cast(0 as bigint) as idx1,charindex(@sep,@str) idx2
	union all
	select idx2+1,charindex(@sep,@str,idx2+1)
	from a
	where idx2>0
)
select substring(@str,idx1,coalesce(nullif(idx2,0),len(@str)+1)-idx1) as value
from a

-- Sample Data
go
Create Table #colors (ID int , EN nvarchar(100), DE nvarchar(100),FR nvarchar(100), PT nvarchar(100))
Insert into #colors(Id, EN,DE,FR,PT)
select 1,N'white',N'weiss',N'blanc',N'branco' union all 
select 2,N'black',N'schwarz',N'noir',N'preto' union all 
select 3,N'red',N'rot',N'rouge',N'vermelho'

go
Create Table #Items(ID int ,ItemID varchar(100), Model varchar(100),Colors varchar(100))
 
Insert into #Items (Id, ItemID, Model, Colors)
select 1,'MT002','S9500','black#white#red' union all
select 2,'MZ412','W8','black#red' union all
select 3,'MZ415','W8s','black#white' union all
select 4,'MZ499','N9500','red' union all
select 5,'MZ599','N0500','' 

-- Selected Language
declare @Language varchar(10)

select @Language='DE'

-- Given Data
select ID, EN,DE,FR,PT from #colors  
select ID, ItemID, Model, colors from #Items

-- Required Data
select ID, ItemID, Model, colors,
	isnull(stuff((select N'#'+ case when @Language='EN' then C.EN
							        when @Language='DE' then C.DE
							        when @Language='FR' then C.FR
							        when @Language='PT' then C.PT
							   else ''
							   end as [text()]
				  from dbo.fnSplitString(colors,'#') M
				  inner join #colors C ON C.EN=M.Value  for xml path('')) 
		  ,1,1,'')
	,'')
from  #Items

-- Drop temp tables
drop table #Colors
drop table #Items

Regards,
GVPrabu
 
Share this answer
 
Comments
Maciej Los 30-Sep-13 8:37am    
Nice ;)
+5!
gvprabu 30-Sep-13 8:40am    
thanks... friend
Member 10305537 30-Sep-13 18:22pm    
Hi!

Wow.. did not expect so complicated solution..
Sorry for stressing so much..

but I understood which is the next step..
never thought to temporary tables..

but have a further question..
since I did not know how to handle with 2 separated query from ASP, one to get all data, among that the color list,

split the value and make a second query to "translate" colors..

thinking at CPU/RAM usage what will be more efficient?
create temporary tables and cancel or make 2 (or more) queries?

Thanks again for your time!

Jan
Hi,
Please find the code sample. Hope it helps
SQL
go
Create Table colors (ID int identity(1,1), EN varchar(100), DE varchar(100),FR	varchar(100), PT varchar(100))
Insert colors values('white','weiss','blanc','branco')
Insert colors values('black','schwarz','noir','preto')
Insert colors values('red','rot','rouge','vermelho')
select * from colors 
go
Create Table Items(ID int identity(1,1),ItemID varchar(100), Model varchar(100),Colors varchar(100))
 
Insert Items values('MT002','S9500','black#white#red')
Insert Items values('MZ412','W8','black#red')
Insert Items values('MZ415','W8s','black#white')
Insert Items values('MZ499','N9500','red')


go
 alter Function GetColorCode
 (
 @ItemID varchar(100),
 @Language varchar(100)
 )
 returns varchar(max)
 as
 Begin 
       Declare @retValue varchar(max)
		
	set @retValue = ''
	Declare @Length int
	Declare @ColorSeperatorpos int
	Declare @ColorValue varchar(100)
	Declare @CurrentColor varchar(100)
	Select @ColorValue  = Colors from Items where  ItemID   = @ItemID
		
	set  @ColorSeperatorpos = CHARINDEX('#', @ColorValue)
	While  (@ColorSeperatorpos  > 0)
	Begin 
  	        Select @CurrentColor  = SUBSTRING(@ColorValue, 0, @ColorSeperatorpos)
		Select @retValue =@retValue   + ( case 
		                                   when @Language = 'EN' then en 
  					           when @Language = 'DE' then de 
  					           when @Language = 'FR' then fr 
 						   when @Language = 'PT' then PT
						end  )   + '#'
			from colors where en =  @CurrentColor

			Set @ColorValue = SUBSTRING(@ColorValue, @ColorSeperatorpos+1, LEN(@ColorValue)- @ColorSeperatorpos)
			Set @ColorSeperatorpos =  CHARINDEX('#', @ColorValue)
		End
		
		if(@ColorValue <> '' )
		Begin 
		     Select @retValue =@retValue   + ( case 
							when @Language = 'EN' then en 
							when @Language = 'DE' then de 
							when @Language = 'FR' then fr 
							when @Language = 'PT' then PT
							end  )   + '#'
			from colors where en =  @ColorValue
		End
		
		return Substring(@retValue,0,LEN(@retValue) )
 End

go 
 
Declare @Language varchar(100) ='fr'
SELECT Items.Model, dbo.GetColorCode( Items.ItemID, @Language) FROM Items 


Regards,Mahe...
 
Share this answer
 
Comments
gvprabu 30-Sep-13 8:00am    
hi....
Nice work... But the problem is If they have 20-30 Colors then we need to change your function... So Better we will try UDF only for Split the values.
The World is full of different wonderful approaches ;)

I don't like to use CASE WHEN ... END[^] statement. My purposal is to use Common Table Expressions[^] (CTE). It isn't exactly what you want, but it shows the way how to resolve your problem.

SQL
--colors table variable
DECLARE @colors TABLE (ID INT IDENTITY(1,1), EN VARCHAR(30), DE VARCHAR(30), FR VARCHAR(30), PT VARCHAR(30))

INSERT INTO @colors (EN, DE, FR, PT)
SELECT 'white', 'weiss', 'blanc', 'branco'
UNION ALL SELECT 'black', 'schwarz', 'noir', 'preto'
UNION ALL SELECT 'red', 'rot', 'rouge', 'vermelho'

--items table variable
DECLARE @items TABLE(ID INT IDENTITY(1,1), ItemID VARCHAR(30), Model VARCHAR(30), Colors VARCHAR(100))

INSERT INTO @items (ItemID, Model, Colors)
SELECT 'MT002', 'S9500', 'black#white#red'
UNION ALL SELECT 'MZ412', 'W8', 'black#red'
UNION ALL SELECT 'MZ415', 'W8s', 'black#white'
UNION ALL SELECT 'MZ499', 'N9500', 'red'

--input parameters:
DECLARE @lng VARCHAR(30)
SET @lng='FR'

DECLARE @products VARCHAR(30)
SET @products = 'MT002,MZ412,MZ415'

--first CTE
--split ItemID into separate rows
;WITH SelectedProducts AS
(
	--initial values
	SELECT LEFT(@products, CHARINDEX(',', @products)-1) AS ItemID, RIGHT(@products, LEN(@products)-CHARINDEX(',', @products)) AS Remainder
	WHERE CHARINDEX(',', @products)>0
	UNION ALL
	--recursive part
	SELECT LEFT(Remainder, CHARINDEX(',', Remainder)-1) AS ItemID, RIGHT(Remainder, LEN(Remainder)-CHARINDEX(',', Remainder)) AS Remainder
	FROM SelectedProducts
	WHERE CHARINDEX(',', Remainder)>0
	UNION ALL
	SELECT Remainder AS ItemID, NULL AS Remainder
	FROM SelectedProducts
	WHERE CHARINDEX(',', Remainder)=0
), CurrentColors AS
--second CTE, split colors 
	(
		--initial value
		SELECT sp.ItemID, i.Model, LEFT(i.Colors, CHARINDEX('#',i.Colors)-1) AS Color, RIGHT(i.Colors, LEN(i.Colors)-CHARINDEX('#',i.Colors)) AS CRemainder
		FROM SelectedProducts AS sp INNER JOIN @items AS i ON i.ItemID = sp.ItemID
		WHERE CHARINDEX('#',i.Colors)>0
		UNION ALL
		--recursive part
		SELECT ItemID, Model, LEFT(CRemainder, CHARINDEX('#',CRemainder)-1) AS Color, RIGHT(CRemainder, LEN(CRemainder)-CHARINDEX('#',CRemainder)) AS CRemainder
		FROM CurrentColors
		WHERE CHARINDEX('#',CRemainder)>0
		UNION ALL
		SELECT ItemID, Model, CRemainder AS Color, NULL AS CRemainder
		FROM CurrentColors
		WHERE CHARINDEX('#',CRemainder)=0
	)
--final result set
		SELECT cc.ItemID, cc.Model, cc.Color AS EN, c.DE, c.FR, c.PT
		FROM CurrentColors AS cc INNER JOIN @colors AS c ON cc.Color=c.EN
		ORDER BY cc.ItemID


Result:
ItemID  Model   EN      DE      FR      PT
MT002	S9500	black	schwarz	noir	preto
MT002	S9500	white	weiss	blanc	branco
MT002	S9500	red	rot	rouge	vermelho
MZ412	W8	red	rot	rouge	vermelho
MZ412	W8	black	schwarz	noir	preto
MZ415	W8s	black	schwarz	noir	preto
MZ415	W8s	white	weiss	blanc	branco



By The Way: i would suggest you to change design of Items table. Instead using english names of colors, use them ID. Also, colors column should store values:
1#2#3
2#3
...etc

Why? It is easiest to fetch color by its ID, than its name (in English).

If you would like to fetch color Id's in any language, you can use UNPIVOT[^] table to achieve that:
SQL
SELECT ID, ColorName, Lngg
FROM (
    SELECT *
    FROM @colors
    ) AS pvt
UNPIVOT(ColorName FOR Lngg IN([EN],[DE],[FR],[PT])) AS unpvt
WHERE Lngg = @lng


Result (in case of 'FR' as an input parameter):
ID      ColorName	Lngg
1	blanc		FR
2	noir		FR
3	rouge		FR
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900