Sorry for this misleading subject, i didn't know how to word better. Because i'm mainly a software-developer, the ternary operator comes to my mind with my following problem.
I need to find the most robust way to link two tables via nullable foreign-key(modModel
and tabSparePart
). The only similarity between both is the model's name and the sparepart's description(the tabSparePart
is an external table from customer that is imported automatically, so it's not my responsibility and i cannot change the data).
Consider the following sparepart-names:
W200I_E/Swap
EXCHANGEUNIT P1i / SILVERBLACK/ CYRILLIC
The modelnames that i want to find are P1i
and W200I_E
.
So there is only one strong rule that i can ensure in the where-clause
:
- there must be a separator
/
and the relevant part is the first one.
Here is the sample data:
Create table #temp(Partname varchar(100))
INSERT INTO #temp
SELECT 'EXCHANGEUNIT P1i / SILVERBLACK/ CYRILLIC' UNION ALL SELECT 'W200I_E/Swap unit/Black'
I would have been finished with following query:
SELECT RTRIM(LEFT(Partname, CHARINDEX('/', Partname) - 1)) AS UNIT
FROM #temp
WHERE CHARINDEX('/', Partname) > 0
... what returns:
EXCHANGEUNIT P1i
W200I_E
But i need P1i
. So i need a way to handle also the case that the first part is separated by whitespaces. In that case i need to select the last word, but only if it is separated at all.
I'm getting a "invalid length parameter passed to the LEFT or SUBSTRING function"
-error with following query:
SELECT REVERSE( LEFT( REVERSE(RTRIM(LEFT(Partname, CHARINDEX('/', Partname) - 1)))
, CHARINDEX(' ', REVERSE(RTRIM(LEFT(Partname, CHARINDEX('/', Partname) - 1))))-1 ))
AS Unit
FROM #temp
WHERE CHARINDEX('/', Partname) > 0
This would work without the second record that has no whitespace. If i would also ensure that the first part contains a whitespace, i would discard valid records.
To cut a long story short, I need to find a way to combine both ways according to the existence of separators.
PS: This has arisen from: Get the last word of a part of a varchar (LEFT/RIGHT)
If anybody is interested, this is the complete (working) stored-procedure. I'm sure i've never used such a strange JOIN
:
CREATE PROC [dbo].[UpdateModelSparePart](@updateCount int output)
with execute as Owner
AS
BEGIN
BEGIN TRANSACTION
UPDATE modModel SET fiSparePart=ModelPart.idSparePart
FROM modModel INNER JOIN
(
SELECT m.idModel
,m.ModelName
,sp.idSparePart
,sp.Price
,Row_Number()Over(Partition By idModel ORDER BY Price DESC)as ModelPrice
FROM modModel AS m INNER JOIN tabSparePart AS sp
ON m.ModelName = CASE
WHEN CHARINDEX(' ', REVERSE(RTRIM(LEFT(sp.SparePartDescription, CHARINDEX('/', sp.SparePartDescription) - 1)))) > 0 THEN
REVERSE( LEFT( REVERSE(RTRIM(LEFT(sp.SparePartDescription, CHARINDEX('/', sp.SparePartDescription) - 1)))
,CHARINDEX(' ', REVERSE(RTRIM(LEFT(sp.SparePartDescription, CHARINDEX('/', sp.SparePartDescription) - 1))))-1 ))
ELSE
RTRIM(LEFT(sp.SparePartDescription, CHARINDEX('/', sp.SparePartDescription) - 1))
END
WHERE (CHARINDEX('/', sp.SparePartDescription) > 0)
GROUP BY idModel,ModelName,idSparePart,Price
)As ModelPart
ON ModelPart.idModel=modModel.idModel
Where ModelPrice=1
SET @updateCount = @@ROWCOUNT;
COMMIT TRANSACTION
END
A more concise version.
I was able to solve the problem:
Ugly but working fine.