简体   繁体   中英

How to match a width and height size with a Regex expression and use Sort By in SQL or C# to build a drop-down?

I've a SQL query which will retrieve the following table, but I want to order the Board size correctly in Descending order (Small to Large) in a drop-down selection. I'm using C# to build the Dropdown selection from the object.

This is what the current SQL query returns.

在此处输入图片说明

DECLARE @StockID int = 680

DECLARE @VariationParent int = (SELECT TOP 1 StockParent_ParentId FROM 
StockVariations SV INNER JOIN FinGoodsParent FGP ON FGP.Id = 
SV.StockParent_ChildId WHERE StockParent_ChildId = @StockID AND SV.IsDeleted = 0 
AND FGP.IsDeleted = 0 AND FGP.Publish = 1) 


 SELECT DISTINCT AV.ID, AV.AttrValue, AV.AttributeTypes_Id 'AttributeTypeID', CAST(CASE WHEN SA.StockParent_Id = @StockID THEN 1 ELSE 0 END as BIT) 'IsDefault' 
   FROM AttributeTypes AT 
  INNER JOIN AttributeValues AV ON AV.AttributeTypes_Id = AT.Id 
  INNER JOIN StockParent_AttributeValues SA on SA.AttributeValue_Id = AV.Id 
  INNER JOIN FinGoodsParent FGP ON FGP.Id = SA.StockParent_Id AND FGP.IsDeleted = 0 AND FGP.Publish = 1
  WHERE SA.StockParent_Id IN (SELECT SV.StockParent_ChildId FROM StockVariations SV INNER JOIN FinGoodsParent FGP ON FGP.Id = SV.StockParent_ChildId AND FGP.IsDeleted = 0 AND FGP.Publish = 1 WHERE SV.StockParent_ParentId = @VariationParent AND SV.IsDeleted = 0) 
  AND SA.IsDeleted = 0 AND AT.IsDeleted = 0 AND AV.IsDeleted = 0
  ORDER BY AV.AttrValue DESC

I've tried to use JQuery code which works, but it replaces the value of the dropdown selection which will prevent my Ajax function from retrieving the correct information.

Here is the JQuery code which kind of works, but I want to either do this in SQL or C# . The code below will do a regex match for anything with numbers and strip out the first number and compare the size. It must be noted that sometimes the sizes in the database can have an x instead of a * separating the values.

<select class="variation-picker">   
    <option value="42">1500*900</option>
    <option value="48">900*900</option>
    <option value="46">2400*600</option>
    <option value="49">600*600</option>
</select>

$( document ).ready(function() {
    $(".variation-picker").html($(".variation-picker option").val(function () {
        return this.text.match(/\d+/);
    }).sort(function (a, b) {
        var a = parseInt(a.value, 10), b = parseInt(b.value, 10);
        return a < b ? -1 : 1;
     }));

    $('.variation-picker').find('option[selected="selected"]').each(function () {
        $(this).prop('selected', true);
    });

});

This is the C# code I'm using in order to build the variation selection dropdowns . The AttrValue column can also contain values such as colour or meters , so it shouldn't just be tied to numeric. I don't really want to create a separate table with order priorities and etc.

if (ProductDetails.ProductVariations?.Count > 0)
        {
            var html = new System.Text.StringBuilder();
            var colCount = 0;

            //Build the variations dropdowns

            ProductDetails.ProductVariations.ForEach(p =>
            {
                if (colCount == 2)
                {
                    colCount = 0;
                    html.AppendLine("</div>");
                    html.AppendLine("<div class='row'>");
                }

                html.AppendLine("<div class='col-md-6 single-variation-div'>");
                html.AppendLine($"<span class='text_select' id='v_{p.ID}'>{p.Name}</span><br />");
                html.AppendLine("<select class='selectpicker variation-picker' data-width='300px' onchange='javascript:ChangeProductVariance();'> ");
                p.ProdVariationValues.ForEach(v => html.AppendLine($"<option value='{v.ID}' { (v.IsDefault ? "selected='selected'" : "") }>{v.AttrValue}</option>"));
                html.AppendLine("</select><br/>");
                html.AppendLine("</div>");

                colCount++;
            });

            ProductVarienceHTML = html.ToString();
        }
        else
        {
            ProductVarienceHTML = "";
        }

我建议您通过以下方法从表结构中解决该问题:通过添加具有(INT)数据类型的高度和宽度的列,然后按(height * width)进行排序

The best solution and fastest solution is doing what @Ahmad Alkaraki said.

Incase you cant then this is a solution that could work. SPLIT the AttrValue and convert it to int, then extraxt width and height , there after extract the size

Have a look at order by

Im not sure if func LAST EXIST in your mssql but you get the idee

 SELECT DISTINCT AV.ID, AV.AttrValue, AV.AttributeTypes_Id 'AttributeTypeID', CAST(CASE WHEN SA.StockParent_Id = @StockID THEN 1 ELSE 0 END as BIT) 'IsDefault',

   FROM AttributeTypes AT 
  INNER JOIN AttributeValues AV ON AV.AttributeTypes_Id = AT.Id 
  INNER JOIN StockParent_AttributeValues SA on SA.AttributeValue_Id = AV.Id 
  INNER JOIN FinGoodsParent FGP ON FGP.Id = SA.StockParent_Id AND FGP.IsDeleted = 0 AND FGP.Publish = 1
  WHERE SA.StockParent_Id IN (SELECT SV.StockParent_ChildId FROM StockVariations SV INNER JOIN FinGoodsParent FGP ON FGP.Id = SV.StockParent_ChildId AND FGP.IsDeleted = 0 AND FGP.Publish = 1 WHERE SV.StockParent_ParentId = @VariationParent AND SV.IsDeleted = 0) 
  AND SA.IsDeleted = 0 AND AT.IsDeleted = 0 AND AV.IsDeleted = 0
  ORDER BY ((SELECT top 1 cast(value as int) FROM STRING_SPLIT(AT.AttrValue, "*") *
            (SELECT cast(LAST(value)) FROM STRING_SPLIT(AT.AttrValue, "*")) DESC

Just in case you can't change your database schema by adding height and width columns:

Let's assume that this is your schema, just for simplifying a little your original query:

CREATE TABLE attributes
    ([AttrValue] varchar(13))
;

INSERT INTO attributes
    ([AttrValue])
VALUES
    ('900*900mm'),
    ('1200*900mm'),
    ('1200*1200mm')
;

Let's create a query that sort by the height * width descending:

SELECT
  attrValue,
  CONVERT(int, (select top 1 value from STRING_SPLIT(attrValue, '*'))) as [leftAttrValue],
  CONVERT(int, (select top 1 LEFT(value, LEN(value) - 2) from STRING_SPLIT(attrValue, '*') where value LIKE '%mm')) as [rightAttrValue]
FROM
  attributes
ORDER BY 
    CONVERT(int, (select top 1 value from STRING_SPLIT(attrValue, '*'))) * 
    CONVERT(int, (select top 1 LEFT(value, LEN(value) - 2) from STRING_SPLIT(attrValue, '*') where value LIKE '%mm'))  DESC
  ;

The result of this query is this:

|   attrValue | leftAttrValue | rightAttrValue |
|-------------|---------------|----------------|
| 1200*1200mm |          1200 |           1200 |
|  1200*900mm |          1200 |            900 |
|   900*900mm |           900 |            900 |

You can test this in this SQL Server fiddle: http://sqlfiddle.com/#!18/691b3/11

So, we will adapt this now to your problem:

SELECT DISTINCT AV.ID, AV.AttrValue, AV.AttributeTypes_Id 'AttributeTypeID', CAST(CASE WHEN SA.StockParent_Id = @StockID THEN 1 ELSE 0 END as BIT) 'IsDefault' 
   FROM AttributeTypes AT 
  INNER JOIN AttributeValues AV ON AV.AttributeTypes_Id = AT.Id 
  INNER JOIN StockParent_AttributeValues SA on SA.AttributeValue_Id = AV.Id 
  INNER JOIN FinGoodsParent FGP ON FGP.Id = SA.StockParent_Id AND FGP.IsDeleted = 0 AND FGP.Publish = 1
  WHERE SA.StockParent_Id IN (SELECT SV.StockParent_ChildId FROM StockVariations SV INNER JOIN FinGoodsParent FGP ON FGP.Id = SV.StockParent_ChildId AND FGP.IsDeleted = 0 AND FGP.Publish = 1 WHERE SV.StockParent_ParentId = @VariationParent AND SV.IsDeleted = 0) 
  AND SA.IsDeleted = 0 AND AT.IsDeleted = 0 AND AV.IsDeleted = 0
  ORDER BY 
      CONVERT(int, (select top 1 value from STRING_SPLIT(AV.AttrValue, '*'))) * 
      CONVERT(int, (select top 1 LEFT(value, LEN(value) - 2) from STRING_SPLIT(AV.AttrValue, '*') where value LIKE '%mm'))  
    DESC

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM