如何将宽度和高度大小与 Regex 表达式匹配并在 SQL 或 C# 中使用 Sort By 来构建下拉列表?
Posted
技术标签:
【中文标题】如何将宽度和高度大小与 Regex 表达式匹配并在 SQL 或 C# 中使用 Sort By 来构建下拉列表?【英文标题】: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? 【发布时间】:2019-12-07 21:48:46 【问题描述】:我有一个 SQL 查询,它将检索下表,但我想在下拉选择中按降序(从小到大)正确排序板尺寸。我正在使用 C# 从对象构建 Dropdown 选择。
这是当前 SQL 查询返回的内容。
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
我尝试使用有效的 JQuery 代码,但它替换了 dropdown 选择的值,这将阻止我的 Ajax 功能从检索正确的信息。
这里是 JQuery 代码,它可以工作,但我想在 SQL 或 C# 中执行此操作。下面的代码将对任何带有数字的东西进行正则表达式匹配,并去掉第一个数字并比较大小。必须注意,有时数据库中的大小可以用 x 而不是 * 分隔值。
<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);
);
);
这是我用来构建变体选择下拉菜单的 C# 代码。 AttrValue 列还可以包含诸如colour
或meters
之类的值,因此它不应仅与数字相关联。我真的不想创建一个包含订单优先级等的单独表格。
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 = "";
【问题讨论】:
我会先开始处理您的数据库。在一列中存储宽度、高度和测量单位违反了第一范式。您应该将它们分成三列,高度、宽度和测量单位(然后您也可以将它们放入另一个表格并参考) 感谢您的回答。我们将尺寸存储在实际产品表上。我们将其用作搜索参数、分组等的元标记。我们将其用作分组标记。 AttrValue 可以包含颜色和其他产品属性等文本。 【参考方案1】:我建议你从表结构中解决它:添加具有(INT)数据类型的高度和宽度的列,然后按(高度*宽度)排序
【讨论】:
【参考方案2】:以防万一您无法通过添加 height
和 width
列来更改数据库架构:
假设这是您的架构,只是为了简化您的原始查询:
CREATE TABLE attributes
([AttrValue] varchar(13))
;
INSERT INTO attributes
([AttrValue])
VALUES
('900*900mm'),
('1200*900mm'),
('1200*1200mm')
;
让我们创建一个按height * width
降序排序的查询:
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
;
这个查询的结果是这样的:
| attrValue | leftAttrValue | rightAttrValue |
|-------------|---------------|----------------|
| 1200*1200mm | 1200 | 1200 |
| 1200*900mm | 1200 | 900 |
| 900*900mm | 900 | 900 |
您可以在此 SQL Server 小提琴中进行测试:http://sqlfiddle.com/#!18/691b3/11
所以,我们现在将根据您的问题进行调整:
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
【讨论】:
感谢您的详细解释。欣赏它。【参考方案3】:最好的解决方案和最快的解决方案就是按照@Ahmad Alkaraki 所说的去做。
如果你不能,那么这是一个可行的解决方案。
SPLIT
AttrValue
并将其转换为 int,然后提取 width
和 height
,然后提取 size
看看order by
我不确定你的 mssql 中是否存在 func LAST
EXIST,但你得到了 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
【讨论】:
以上是关于如何将宽度和高度大小与 Regex 表达式匹配并在 SQL 或 C# 中使用 Sort By 来构建下拉列表?的主要内容,如果未能解决你的问题,请参考以下文章