Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2005 Forums
 Transact-SQL (2005)
 SET BASED solution to this problem?

Author  Topic 

Abu-Dina
Posting Yak Master

206 Posts

Posted - 2008-04-23 : 10:59:05
Greetings all,

Looking for a set based solution to the following SQL problem. I've got a solution that uses a while loop but I have a feeling that there is a better way to do this!

I will use a simplified dataset as an example as I don't want to swamp you with too much detail about my real table structures etc...

I have the following tables (plus some sample data) :


insert into dbo.VehicleModel
select 1, 'RT 100', NULL union all
select 2, 'TGB ACKROS TEC', NULL union all
select 3, 'TB 50 PREDATOR 2', NULL union all
select 4, 'TGB 409 CRUISE 50', NULL union all
select 5, 'ESCOR SUPER SONIC 400SL', NULL union all
select 6, 'SUPER SONIC 150 XI', NULL union all
select 7, 'RT X 350 SERIES', NULL union all
select 8, 'TB SALON 4000', NULL


create table dbo.VehicleModelNorm (
VehicleModelNormId int
,VehicleModelNorm varchar(100)
)

insert into dbo.VehicleModelNorm
select 1, 'ACE' union all
select 2, 'TGB ACKROS' union all
select 3, 'SUPER SONIC' union all
select 4, 'TB 50' union all
select 5, 'RT' union all
select 6, 'TGB' union all
select 7, 'RT' union all
select 8, 'TB SALON'


What I need to do is update the VehicleModelNorm column in VehicleModel with the relevant ID from the VehicleModelNorm table. Sounds easy enough BUT here is the catch. In my vehicles table the VehicleModel are the actual vehicle model names. In my vehicleNorm table I have a more generalized name. What I want to do is look at each VehicleModel, try to find a match in the VehicleModelNorm table, if there is no match then chop off the last word and look again.

For example, starting with 'RT 100 7 SERIES', I want to try to find an exact match for that in my vehicleModelNorm table. If there is no match, remove the last word and look for 'RT 100 7' then look for 'RT 100' etc...

How can I do this in a set based solution? I can do this with a WHILE loop but I have a feeling it might be possible to do this with a CTE but I just can't get my head round it.

Your advice would be much appreciated!

harsh_athalye
Master Smack Fu Yak Hacker

5581 Posts

Posted - 2008-04-23 : 11:06:06
May be this?

Update vm
set VehicleModelNormId = vmn.VehicleModelNormId
from VehicleModel vm JOIN VehicleModelNorm vmn
on vm.VehicleModel like vmn.VehicleModelNorm + '%'


Harsh Athalye
India.
"The IMPOSSIBLE is often UNTRIED"
Go to Top of Page

RyanRandall
Master Smack Fu Yak Hacker

1074 Posts

Posted - 2008-04-23 : 11:06:10
Questions...

What would you want to update VehicleModelIds 4, 7 and 8 to?

What do you want to do if there is more than one VehicleModelNormId match?

Ryan Randall
Solutions are easy. Understanding the problem, now, that's the hard part.
Go to Top of Page

RyanRandall
Master Smack Fu Yak Hacker

1074 Posts

Posted - 2008-04-23 : 11:10:07
Yep - my first try would be similar to harsh's...

update a set VehicleModelNormId = b.VehicleModelNormId
from dbo.VehicleModel a inner join dbo.VehicleModelNorm b
on ' ' + a.VehicleModel + ' ' LIKE '% ' + b.VehicleModelNorm + ' %'


Ryan Randall
Solutions are easy. Understanding the problem, now, that's the hard part.
Go to Top of Page

Abu-Dina
Posting Yak Master

206 Posts

Posted - 2008-04-23 : 11:19:21
Hi guys,

Thanks for your speedy responses but that would not work. I've updated my sample data, if you run it you will see why. It won't work for SUPER SONIC. Also your update looks for any word in the VehModelNorm string but that is incorrect.

Thanks
Go to Top of Page

harsh_athalye
Master Smack Fu Yak Hacker

5581 Posts

Posted - 2008-04-23 : 11:27:30
>> your update looks for any word in the VehModelNorm string but that is incorrect

Not quite so. It looks for string starting with the word in VehicleNorm field not any word. Also the update wont work for ESCOR SUPER SONIC, because obviously it is non-matching as per your original requirement.

If you want exact answers, you should give exact specs!

Harsh Athalye
India.
"The IMPOSSIBLE is often UNTRIED"
Go to Top of Page

RyanRandall
Master Smack Fu Yak Hacker

1074 Posts

Posted - 2008-04-23 : 11:28:30
Please don't update the original request - we lose the flow of the thread. Also, what you've updated it to needs some tidying (we're missing a create and the names have changed).

Ryan Randall
Solutions are easy. Understanding the problem, now, that's the hard part.
Go to Top of Page

RyanRandall
Master Smack Fu Yak Hacker

1074 Posts

Posted - 2008-04-23 : 11:29:13
Also, you've not yet answered my questions.


Ryan Randall
Solutions are easy. Understanding the problem, now, that's the hard part.
Go to Top of Page

Abu-Dina
Posting Yak Master

206 Posts

Posted - 2008-04-23 : 11:33:40
Fair enough. I copied Ryan's code whch I thought is the same as yours but there is a subtle difference. Yours seems to work so I will test it a little more and report back.

Thanks for the help.
Go to Top of Page

Abu-Dina
Posting Yak Master

206 Posts

Posted - 2008-04-23 : 11:34:29
Okay... you both need to calm down. I am human, I can make mistakes also! Ryan, I modified my sample data to reflect your original query.
Go to Top of Page

RyanRandall
Master Smack Fu Yak Hacker

1074 Posts

Posted - 2008-04-23 : 11:38:23
quote:
also
How dare you!

Ryan Randall
Solutions are easy. Understanding the problem, now, that's the hard part.
Go to Top of Page

Abu-Dina
Posting Yak Master

206 Posts

Posted - 2008-04-24 : 05:42:19
Hi again guys,

Apologies for provding dodgy sample data. I was stressed yesterday afternoon and wasn't thinking straight. Anyway, back to my originl problem. This time I will provide a better set of sample data so hopefully one of your gurus out there can help me find a solution.

Better sample data:


if object_id('VehicleModel') > 0
drop table dbo.VehicleModel

create table dbo.VehicleModel (
VehicleModelId int
,VehicleModel varchar(100)
,VehicleModelNormId int
)

insert into dbo.VehicleModel
select 1, 'RT 100', NULL union all
select 2, 'TGB ACKROS TEC', NULL union all
select 3, 'TB 50 PREDATOR 2', NULL union all
select 4, 'TGB 409 CRUISE 50', NULL union all
select 5, 'ESCOR SUPER SONIC 400SL', NULL union all
select 6, 'SUPER SONIC 150 XI', NULL union all
select 7, 'RT X 350 SERIES', NULL union all
select 8, 'TB SALON 4000', NULL union all
select 9, 'AERO 100', NULL union all
select 10 , 'AERO 50', NULL union all
select 11, 'A 170 ELEGANCE SE', NULL union all
select 12, 'A 150 CLASSIC SE', NULL union all
select 13, 'A 150 SPECIAL EDITION', NULL union all
select 14, 'GTV 2.0', NULL union all
select 15, 'GTV 600 XL', NULL


if object_id('VehicleModelNorm') > 0
drop table dbo.VehicleModelNorm

create table dbo.VehicleModelNorm (
VehicleModelNormId int
,VehicleModelNorm varchar(100)
)

insert into dbo.VehicleModelNorm
select 1, 'ACE' union all
select 2, 'TGB ACKROS' union all
select 3, 'SUPER SONIC' union all
select 4, 'TB 50' union all
select 5, 'RT' union all
select 6, 'TGB' union all
select 7, 'RT' union all
select 8, 'TB SALON' union all
select 9, 'A' union all
select 10, 'AERO' union all
select 11, 'GTV' union all
select 12, 'GT'


With harsh's solution, the ModelNormIds are not populated correctly but that's not his fault as my previous sample data was incomplete.

The idea here is to take a VehicleModel, look for a match in the VehicleodelNorm table, if there is no match, chop off the last word from the VehicleModel and loko again, so this is repeated until there is only one word left in the VehcileModel. If there is still no match then so be it, no ID is found.

For example:

VehicleModel : GTV 600 XL

there is no mtahc for this in the VehicleMOdelNorm table. We take off the last word and look for GTV 600, still no match so we try GTV, bingo! there is a match so we can insert that VehicleModelNormId for that record.

As I said before, I can do this witha while loop but is there a set based solution for this?

Your advice would be appreciated once again!



Go to Top of Page

harsh_athalye
Master Smack Fu Yak Hacker

5581 Posts

Posted - 2008-04-24 : 05:59:31
What about VehicleModel - 'ESCOR SUPER SONIC 400SL' ?

Harsh Athalye
India.
"The IMPOSSIBLE is often UNTRIED"
Go to Top of Page

RyanRandall
Master Smack Fu Yak Hacker

1074 Posts

Posted - 2008-04-24 : 06:00:31
So 'ESCOR SUPER SONIC 400SL' should map to nothing, yes? Using your algorithm...

ESCOR SUPER SONIC 400SL -> no
ESCOR SUPER SONIC -> no
ESCOR SUPER -> no
ESCOR -> no


Ryan Randall
Solutions are easy. Understanding the problem, now, that's the hard part.
Go to Top of Page

RyanRandall
Master Smack Fu Yak Hacker

1074 Posts

Posted - 2008-04-24 : 06:03:53
Also, why do you have 'RT' twice in VehicleModelNorm?

Ryan Randall
Solutions are easy. Understanding the problem, now, that's the hard part.
Go to Top of Page

Abu-Dina
Posting Yak Master

206 Posts

Posted - 2008-04-24 : 06:04:06
quote:
Originally posted by RyanRandall

So 'ESCOR SUPER SONIC 400SL' should map to nothing, yes? Using your algorithm...

ESCOR SUPER SONIC 400SL -> no
ESCOR SUPER SONIC -> no
ESCOR SUPER -> no
ESCOR -> no


Ryan Randall
Solutions are easy. Understanding the problem, now, that's the hard part.



Sure... not every single one has to matc for this exercise. BTW this is a typo but I won't change it. I nkow you guys don't like edited posts!
Go to Top of Page

Abu-Dina
Posting Yak Master

206 Posts

Posted - 2008-04-24 : 06:04:54
quote:
Originally posted by RyanRandall

Also, why do you have 'RT' twice in VehicleModelNorm?

Ryan Randall
Solutions are easy. Understanding the problem, now, that's the hard part.



Grrr!! That's a mistake... it shouldn't be there.
Go to Top of Page

RyanRandall
Master Smack Fu Yak Hacker

1074 Posts

Posted - 2008-04-24 : 06:10:13
Well this would be my next stab then...

update a set VehicleModelNormId = (select top 1 VehicleModelNormId from dbo.VehicleModelNorm where
' ' + a.VehicleModel + ' ' LIKE ' ' + VehicleModelNorm + ' %' order by len(VehicleModelNorm) desc)
from dbo.VehicleModel a

/* Results
VehicleModelId VehicleModel VehicleModelNormId VehicleModelNorm
-------------- ------------------------------ ------------------ --------------------
1 RT 100 7 RT
2 TGB ACKROS TEC 2 TGB ACKROS
3 TB 50 PREDATOR 2 4 TB 50
4 TGB 409 CRUISE 50 6 TGB
5 ESCOR SUPER SONIC 400SL NULL NULL
6 SUPER SONIC 150 XI 3 SUPER SONIC
7 RT X 350 SERIES 7 RT
8 TB SALON 4000 8 TB SALON
9 AERO 100 10 AERO
10 AERO 50 10 AERO
11 A 170 ELEGANCE SE 9 A
12 A 150 CLASSIC SE 9 A
13 A 150 SPECIAL EDITION 9 A
14 GTV 2.0 11 GTV
15 GTV 600 XL 11 GTV
*/


Ryan Randall
Solutions are easy. Understanding the problem, now, that's the hard part.
Go to Top of Page

Abu-Dina
Posting Yak Master

206 Posts

Posted - 2008-04-24 : 06:24:53
Ryan, I want to hug you.. lol
Thanks for your help. Much appreciated. Now I got to figure out why this works.

Thanks once again.
Go to Top of Page

RyanRandall
Master Smack Fu Yak Hacker

1074 Posts

Posted - 2008-04-24 : 07:27:14
<Group hug>

Re understanding it, it might help to understand the approach to solving it...

1. Join the tables together based on some matching criteria

select * from dbo.VehicleModel a left outer join dbo.VehicleModelNorm b on
' ' + a.VehicleModel + ' ' LIKE ' ' + VehicleModelNorm + ' %'
order by VehicleModelId
2. Figure out the criteria for which row to select - hence my question "What do you want to do if there is more than one VehicleModelNormId match?". As it turned out, you wanted the 'longest' match.

3. Modify the query to give you only this (using top 1 with a sort is a neat way to do this 'in one go')

select *, (select top 1 VehicleModelNormId from dbo.VehicleModelNorm where
' ' + a.VehicleModel + ' ' LIKE ' ' + VehicleModelNorm + ' %' order by len(VehicleModelNorm) desc)
from dbo.VehicleModel a
4. Modify this to create the final update statement


Ryan Randall
Solutions are easy. Understanding the problem, now, that's the hard part.
Go to Top of Page

Abu-Dina
Posting Yak Master

206 Posts

Posted - 2008-04-28 : 05:47:17
quote:
Originally posted by RyanRandall

<Group hug>

Re understanding it, it might help to understand the approach to solving it...

1. Join the tables together based on some matching criteria

select * from dbo.VehicleModel a left outer join dbo.VehicleModelNorm b on
' ' + a.VehicleModel + ' ' LIKE ' ' + VehicleModelNorm + ' %'
order by VehicleModelId
2. Figure out the criteria for which row to select - hence my question "What do you want to do if there is more than one VehicleModelNormId match?". As it turned out, you wanted the 'longest' match.

3. Modify the query to give you only this (using top 1 with a sort is a neat way to do this 'in one go')

select *, (select top 1 VehicleModelNormId from dbo.VehicleModelNorm where
' ' + a.VehicleModel + ' ' LIKE ' ' + VehicleModelNorm + ' %' order by len(VehicleModelNorm) desc)
from dbo.VehicleModel a
4. Modify this to create the final update statement


Ryan Randall
Solutions are easy. Understanding the problem, now, that's the hard part.



Well explained Ryan. Makes perfect sense. Thanks once again.
Go to Top of Page
    Next Page

- Advertisement -