| 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.VehicleModelselect 1, 'RT 100', NULL union allselect 2, 'TGB ACKROS TEC', NULL union allselect 3, 'TB 50 PREDATOR 2', NULL union allselect 4, 'TGB 409 CRUISE 50', NULL union allselect 5, 'ESCOR SUPER SONIC 400SL', NULL union allselect 6, 'SUPER SONIC 150 XI', NULL union allselect 7, 'RT X 350 SERIES', NULL union allselect 8, 'TB SALON 4000', NULLcreate table dbo.VehicleModelNorm ( VehicleModelNormId int ,VehicleModelNorm varchar(100) )insert into dbo.VehicleModelNorm select 1, 'ACE' union allselect 2, 'TGB ACKROS' union allselect 3, 'SUPER SONIC' union allselect 4, 'TB 50' union allselect 5, 'RT' union allselect 6, 'TGB' union allselect 7, 'RT' union allselect 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 vmset VehicleModelNormId = vmn.VehicleModelNormIdfrom VehicleModel vm JOIN VehicleModelNorm vmnon vm.VehicleModel like vmn.VehicleModelNorm + '%' Harsh AthalyeIndia."The IMPOSSIBLE is often UNTRIED" |
 |
|
|
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. |
 |
|
|
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.VehicleModelNormIdfrom 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. |
 |
|
|
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 |
 |
|
|
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 incorrectNot 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 AthalyeIndia."The IMPOSSIBLE is often UNTRIED" |
 |
|
|
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. |
 |
|
|
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. |
 |
|
|
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. |
 |
|
|
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. |
 |
|
|
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. |
 |
|
|
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') > 0drop table dbo.VehicleModelcreate table dbo.VehicleModel ( VehicleModelId int ,VehicleModel varchar(100) ,VehicleModelNormId int )insert into dbo.VehicleModelselect 1, 'RT 100', NULL union allselect 2, 'TGB ACKROS TEC', NULL union allselect 3, 'TB 50 PREDATOR 2', NULL union allselect 4, 'TGB 409 CRUISE 50', NULL union allselect 5, 'ESCOR SUPER SONIC 400SL', NULL union allselect 6, 'SUPER SONIC 150 XI', NULL union allselect 7, 'RT X 350 SERIES', NULL union allselect 8, 'TB SALON 4000', NULL union allselect 9, 'AERO 100', NULL union allselect 10 , 'AERO 50', NULL union allselect 11, 'A 170 ELEGANCE SE', NULL union allselect 12, 'A 150 CLASSIC SE', NULL union allselect 13, 'A 150 SPECIAL EDITION', NULL union allselect 14, 'GTV 2.0', NULL union allselect 15, 'GTV 600 XL', NULLif object_id('VehicleModelNorm') > 0drop table dbo.VehicleModelNormcreate table dbo.VehicleModelNorm ( VehicleModelNormId int ,VehicleModelNorm varchar(100) )insert into dbo.VehicleModelNorm select 1, 'ACE' union allselect 2, 'TGB ACKROS' union allselect 3, 'SUPER SONIC' union allselect 4, 'TB 50' union allselect 5, 'RT' union allselect 6, 'TGB' union allselect 7, 'RT' union allselect 8, 'TB SALON' union allselect 9, 'A' union allselect 10, 'AERO' union allselect 11, 'GTV' union allselect 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 XLthere 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! |
 |
|
|
harsh_athalye
Master Smack Fu Yak Hacker
5581 Posts |
Posted - 2008-04-24 : 05:59:31
|
| What about VehicleModel - 'ESCOR SUPER SONIC 400SL' ?Harsh AthalyeIndia."The IMPOSSIBLE is often UNTRIED" |
 |
|
|
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 -> noESCOR SUPER SONIC -> noESCOR SUPER -> noESCOR -> noRyan Randall Solutions are easy. Understanding the problem, now, that's the hard part. |
 |
|
|
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. |
 |
|
|
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 -> noESCOR SUPER SONIC -> noESCOR SUPER -> noESCOR -> noRyan 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! |
 |
|
|
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. |
 |
|
|
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/* ResultsVehicleModelId VehicleModel VehicleModelNormId VehicleModelNorm-------------- ------------------------------ ------------------ --------------------1 RT 100 7 RT2 TGB ACKROS TEC 2 TGB ACKROS3 TB 50 PREDATOR 2 4 TB 504 TGB 409 CRUISE 50 6 TGB5 ESCOR SUPER SONIC 400SL NULL NULL6 SUPER SONIC 150 XI 3 SUPER SONIC7 RT X 350 SERIES 7 RT8 TB SALON 4000 8 TB SALON9 AERO 100 10 AERO10 AERO 50 10 AERO11 A 170 ELEGANCE SE 9 A12 A 150 CLASSIC SE 9 A13 A 150 SPECIAL EDITION 9 A14 GTV 2.0 11 GTV15 GTV 600 XL 11 GTV*/ Ryan Randall Solutions are easy. Understanding the problem, now, that's the hard part. |
 |
|
|
Abu-Dina
Posting Yak Master
206 Posts |
Posted - 2008-04-24 : 06:24:53
|
| Ryan, I want to hug you.. lolThanks for your help. Much appreciated. Now I got to figure out why this works.Thanks once again. |
 |
|
|
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 criteriaselect * 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 statementRyan Randall Solutions are easy. Understanding the problem, now, that's the hard part. |
 |
|
|
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 criteriaselect * 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 statementRyan Randall Solutions are easy. Understanding the problem, now, that's the hard part.
Well explained Ryan. Makes perfect sense. Thanks once again. |
 |
|
|
Next Page
|