如何用正则匹配尺寸并在SQL/C#中排序生成下拉选单
解决下拉菜单中板材尺寸排序问题(不破坏Value值)
推荐方案:从SQL查询层面实现智能排序
这是最稳妥的方案,直接从数据库获取排好序的数据,前端无需额外处理,完美避免前端排序导致的Value值异常问题。
原SQL的ORDER BY AV.AttrValue DESC是按字符串字典序排序,会导致"900900"排在"1500900"前面这类混乱情况。我们可以通过CASE WHEN逻辑区分尺寸类和非尺寸类值,对尺寸提取数值进行排序,非尺寸类按原字符串排序:
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 -- 优先按尺寸的第一个数值排序(非尺寸类给大数,排后面) CASE WHEN CHARINDEX('*', AV.AttrValue) > 0 OR CHARINDEX('x', AV.AttrValue) > 0 THEN CAST(LEFT(AV.AttrValue, CHARINDEX(CASE WHEN CHARINDEX('*', AV.AttrValue) > 0 THEN '*' ELSE 'x' END, AV.AttrValue) - 1) AS INT) ELSE 999999 END ASC, -- 尺寸的第二个数值排序 CASE WHEN CHARINDEX('*', AV.AttrValue) > 0 OR CHARINDEX('x', AV.AttrValue) > 0 THEN CAST(SUBSTRING(AV.AttrValue, CHARINDEX(CASE WHEN CHARINDEX('*', AV.AttrValue) > 0 THEN '*' ELSE 'x' END, AV.AttrValue) + 1, LEN(AV.AttrValue)) AS INT) ELSE 0 END ASC, -- 非尺寸类按原文本排序 AV.AttrValue ASC
逻辑说明:
- 先判断
AttrValue是否包含*或x(尺寸标识),如果是则提取前后的数字转为整数,先按第一个数字升序,再按第二个数字升序。 - 非尺寸类(如颜色、米数)会被分配一个大数值(999999),排在尺寸类之后,然后按原字符串自然排序。
- 完全不需要额外的排序表,直接在查询中处理所有场景。
前端备选方案(若无法修改SQL)
如果暂时不能调整SQL,可以修改jQuery代码,绝不修改Option的Value值,仅根据文本内容排序Option元素,同时保留原选中状态:
$(document).ready(function() { // 先保存每个下拉框的原选中值,避免排序后丢失 $(".variation-picker").each(function() { $(this).data("original-selected", $(this).val()); }); // 对每个下拉框进行排序 $(".variation-picker").each(function() { const $select = $(this); const $options = $select.find("option").sort((a, b) => { const aText = $(a).text().trim(); const bText = $(b).text().trim(); // 判断是否为标准尺寸格式(数字+*或x+数字) const isASize = /^\d+[*x]\d+$/.test(aText); const isBSize = /^\d+[*x]\d+$/.test(bText); if (isASize && isBSize) { // 拆分尺寸为两个数字维度 const [a1, a2] = aText.split(/[*x]/).map(Number); const [b1, b2] = bText.split(/[*x]/).map(Number); // 先比较第一个维度,再比较第二个维度 if (a1 !== b1) return a1 - b1; return a2 - b2; } else if (isASize) { // 尺寸类优先排在前面 return -1; } else if (isBSize) { return 1; } else { // 非尺寸类按文本自然排序 return aText.localeCompare(bText); } }); // 重新渲染下拉框并恢复原选中值 $select.empty().append($options); const originalValue = $select.data("original-selected"); if (originalValue) $select.val(originalValue); }); });
改进点:
- 完全不触碰Option的
value属性,彻底解决Ajax获取错误值的问题。 - 智能区分尺寸类和非尺寸类,尺寸按数值逻辑排序,非尺寸按文本排序。
- 提前保存原选中状态,排序后自动恢复,避免用户选中的选项丢失。
C#代码无需修改
无论使用哪种方案,你的C#渲染代码都不需要调整:如果用SQL方案,数据已经排好序,直接循环渲染即可;如果用前端方案,前端会自动处理排序,C#保持原样输出就行。
内容的提问来源于stack exchange,提问作者Tig7r
相关产品推荐
相关产品推荐

