jacob-on-stackoverflow jacob-on-stackoverflow - 2 months ago 10
PHP Question

Sorting by similarity in alphanumeric string MS SQL Server 2012

I've inherited a project that is using a PHP script to access a SQL Server 2012 database. The application allows a user to input several parameters and make a request based on those parameters.

The piece I'm having problems with is a field that allows users to search for an item with a SKU beginning with a string of alphanumeric characters.

This is the query that was used by the project:

SELECT top 10 IB.LocalSKU
, Cast(Round(IB.GoalMargin, 2) AS Decimal(10,2)) AS GoalMargin
, CASE WHEN IB.MAP = 0 THEN NULL ELSE IB.MAP END AS Min
, IB.ProductCost
, IB.ShippingEstimate
, EB.Price AS CurrentPrice


FROM intra.InventoryBase IB INNER JOIN intra.DropshipChannelAdvisorSKUs CA
ON IB.LocalSKU = CA.LocalSKU
LEFT JOIN intra.eBayQoHFeedback EB
ON CA.ChannelAdvisorSKU = EB.SKU

WHERE LOWER(IB.LocalSKU) LIKE LOWER('$localSKU%')
AND LOWER(SupplierID) LIKE LOWER('%$supplierId%')
AND LOWER(IB.Category) LIKE LOWER('%$category%')
AND LOWER(IB.Dropship) LIKE LOWER('%$dropship%');


I have noticed that the query returns the correct information, but not in a useful order.

I am not sure how to sort it so that the rows with SKUs most closely matching the $localSKU variable are ranked first.

I attempted this, but it didn't have the effect I hoped for:

ORDER BY Difference(IB.LocalSKU, '$localSKU%') ASC


I've also done some reading on Fuzzy String matching, but I'm not sure how to implement it here.

Is there an effective way to:


  1. Search for a varchar starting with a given string

  2. Order results based on the closeness of that string, then by value



Expected Result:

Parameters:

$localSKU = "FMCPL1CY00";
$supplierId = 87;
$category = "Premium Floor Liners";
$dropship = True;


Expected results:

--------------------------------------------------------------------------------
| FMCPL1CY00* | GoalMargin | 0 | ProductCost | ShippingEstimate | CurrentPrice |
| FMCPL1CY01* | GoalMargin | 0 | ProductCost | ShippingEstimate | CurrentPrice |
| FMCPL1CY02* | GoalMargin | 0 | ProductCost | ShippingEstimate | CurrentPrice |
| FMCPL1CY03* | GoalMargin | 0 | ProductCost | ShippingEstimate | CurrentPrice |
--------------------------------------------------------------------------------


Actual Results:

-------------------------------------------------------------------------------------
| FMCPL1CH04221509 | GoalMargin | 0 | ProductCost | ShippingEstimate | CurrentPrice |
| FMCPM1SA0021302 | GoalMargin | 0 | ProductCost | ShippingEstimate | CurrentPrice |
| FMCPL1TY07801509 | GoalMargin | 0 | ProductCost | ShippingEstimate | CurrentPrice |
| FMCPL1TY05721502 | GoalMargin | 0 | ProductCost | ShippingEstimate | CurrentPrice |
-------------------------------------------------------------------------------------

Answer

Try this query:

SELECT top 10 IB.LocalSKU
, Cast(Round(IB.GoalMargin, 2) AS Decimal(10,2)) AS GoalMargin
, CASE WHEN IB.MAP = 0 THEN NULL ELSE IB.MAP END AS Min
, IB.ProductCost
, IB.ShippingEstimate
, EB.Price AS CurrentPrice

,CASE WHEN IB.LocalSKU LIKE '$localSKU%' THEN 0  else 1 END as MyOrder

FROM intra.InventoryBase IB INNER JOIN intra.DropshipChannelAdvisorSKUs CA
  ON IB.LocalSKU = CA.LocalSKU
LEFT JOIN intra.eBayQoHFeedback EB
  ON CA.ChannelAdvisorSKU = EB.SKU

WHERE LOWER(IB.LocalSKU) LIKE LOWER('$localSKU%')
  AND LOWER(SupplierID) LIKE LOWER('%$supplierId%')
  AND LOWER(IB.Category) LIKE LOWER('%$category%')
  AND LOWER(IB.Dropship) LIKE LOWER('%$dropship%')

ORDER BY MyOrder ASC;

I hope it helps.