Sql 从表中获取最大数量添加一个并使用特定约定进行检查

Sql 从表中获取最大数量添加一个并使用特定约定进行检查,sql,sql-server,Sql,Sql Server,我必须根据某种约定生成artikel数,该约定如下 位数 {1 or 2 or 3}.{4 or 5}.{n} 产品编号示例: 7.1001.1 1.1453.1 3.5436.1 12.7839.1 12.3232.1 13.7676.1 3.34565.1 12.56433.1 247.23413.1 第一部分以产品为基础,每个产品都有自己的编号。比如Rebook-12、Nike-256和Umbro-3 我必须传递这个数字并在表中签入,如果有一些行包含它,例如我传递12,那么我应该得到从

我必须根据某种约定生成artikel数,该约定如下

位数

{1 or 2 or 3}.{4 or 5}.{n}
产品编号示例:

7.1001.1
1.1453.1
3.5436.1
12.7839.1
12.3232.1
13.7676.1
3.34565.1
12.56433.1
247.23413.1
第一部分以产品为基础,每个产品都有自己的编号。比如Rebook-12、Nike-256和Umbro-3

我必须传递这个数字并在表中签入,如果有一些行包含它,例如我传递12,那么我应该得到从12开始的所有内容

现在应该有三种情况下该怎么办:

第一种情况:表中没有行:

12.1001.1
...
12.9999.1
Using cmd As New SqlCommand("SELECT CASE WHEN r.number Is NULL THEN 1001
                                                     WHEN r.number = 9999 THEN 10001
                                                     Else r.number + 1 End number
                                        FROM (VALUES(@producentNumber)) AS a(art)   -- this will search this number within inner query And make case..
                                        LEFT JOIN(
                                        -- Get producent (in Like) number And max number Of it (without Like it Get all producent numbers And their max number out Of all
                                        SELECT PARSENAME(Nummer, 3) art,
                                        MAX(CAST(PARSENAME(Nummer, 2) AS INT)) number
                                        FROM tbArtikel WHERE Nummer Like '@producentNumber' + '[.]%'
                                        GROUP BY PARSENAME(Nummer, 3)
                                        ) r
                                        On r.art = a.art", con)



                cmd.CommandType = CommandType.Text
                cmd.Parameters.AddWithValue("@producentNumber", producentNumber)
然后检索1001

第二种情况:如果有行

因此,可以肯定的是,至少已经有一个:

12.1001.1
如果他们是这样的话,我们可以说:

12.1002.1
12.1003.1
...
12.4345.1
12.1002.1
12.1003.1
...
12.9999.1
所以应该检索下一个所以:4346

如果这个产品已经有5位数了,那么我们就说:

12.1002.1
12.1003.1
...
12.4345.1
12.1002.1
12.1003.1
...
12.9999.1
所以应该检索下一个所以:10001

第三种情况:事实上与第二种情况相同,但如果第二种情况的轴为9999:

12.1001.1
...
12.9999.1
Using cmd As New SqlCommand("SELECT CASE WHEN r.number Is NULL THEN 1001
                                                     WHEN r.number = 9999 THEN 10001
                                                     Else r.number + 1 End number
                                        FROM (VALUES(@producentNumber)) AS a(art)   -- this will search this number within inner query And make case..
                                        LEFT JOIN(
                                        -- Get producent (in Like) number And max number Of it (without Like it Get all producent numbers And their max number out Of all
                                        SELECT PARSENAME(Nummer, 3) art,
                                        MAX(CAST(PARSENAME(Nummer, 2) AS INT)) number
                                        FROM tbArtikel WHERE Nummer Like '@producentNumber' + '[.]%'
                                        GROUP BY PARSENAME(Nummer, 3)
                                        ) r
                                        On r.art = a.art", con)



                cmd.CommandType = CommandType.Text
                cmd.Parameters.AddWithValue("@producentNumber", producentNumber)
然后返回的值应为:10001

所以应该检索下一个所以:10003

希望你明白我的意思

我已经开始做点什么了。这段代码是采取生产编号-寻找所有行开始与它,然后只是简单地添加1到第二部分不幸的是,我不知道我应该如何改变它根据这3种情况

select
    parsename(max(nummer), 3) + '.'                    -- 3
    + ltrim(max(cast(parsename(nummer, 2) as int) +1)) -- 5436 -> 5437
    + '.1'                                          
from tbArtikel 
where Nummer LIKE '3.%'
指望你的帮助。如果有不清楚的地方,请告诉我

附加问题:

12.1001.1
...
12.9999.1
Using cmd As New SqlCommand("SELECT CASE WHEN r.number Is NULL THEN 1001
                                                     WHEN r.number = 9999 THEN 10001
                                                     Else r.number + 1 End number
                                        FROM (VALUES(@producentNumber)) AS a(art)   -- this will search this number within inner query And make case..
                                        LEFT JOIN(
                                        -- Get producent (in Like) number And max number Of it (without Like it Get all producent numbers And their max number out Of all
                                        SELECT PARSENAME(Nummer, 3) art,
                                        MAX(CAST(PARSENAME(Nummer, 2) AS INT)) number
                                        FROM tbArtikel WHERE Nummer Like '@producentNumber' + '[.]%'
                                        GROUP BY PARSENAME(Nummer, 3)
                                        ) r
                                        On r.art = a.art", con)



                cmd.CommandType = CommandType.Text
                cmd.Parameters.AddWithValue("@producentNumber", producentNumber)

我不完全理解你的要求。我不确定这些例子……但是如果我在做的话,我会尝试先把这个字段分成3个字段,然后用它们做一些事情。

希望在3个字段被分解后,现在对它们应用逻辑会容易得多

更新: 好吧,我重读了你的问题,我知道你想说什么。。 如果用户搜索一个不存在的值,例如8。 那你想退回1001 如果他们搜索任何其他有结果的内容,则返回max+1 除非是9999,否则返回10001。 如果这是正确的,那么检查这个

只需更改@search变量即可查看其结果
我认为可能有一种更干净的方法来实现这一点,但我现在没有想到:(

如果你真的不能添加两个新字段(这可能不是最简单、最快的解决方案),并且可能无法添加函数索引,您必须提取第2部分编号并获得最大值,增量,然后与您的条件第1部分编号和结尾处的“.1”连接:

SELECT :par1 || '.' || (Max(To_Number(SubStr(nummer, dot1 + 1, dot2 - dot1 -1 ))) + 1) || '.1' NEW_number
--SELECT SubStr(nummer, 1, dot1 - 1) N1st, SubStr(nummer, dot1 + 1, dot2 - dot1 -1 ) N2nd,  SubStr(nummer, dot2 + 1) N1th
FROM (
SELECT nummer, InStr(nummer, '.') dot1, InStr(nummer, '.', 1, 2) dot2 
FROM tbArtikel
WHERE nummer LIKE :par1 || '.%')
;      
--GROUP BY SubStr(nummer, 1, dot1 – 1)
这是针对oracle sql的,我没有sql serwer进行测试,但这可能是最简单的答案:

select @par1 + '.' + (select max(cast(SUBSTRING(nummer, CHARINDEX( '.', nummer, 1 ) +1, CHARINDEX( '.', nummer, CHARINDEX( '.', nummer, 1 ) +1 ) - CHARINDEX( '.', nummer, 1 ) -1) as int)) + 1 from tbArtikel where nummer LIKE @par1 || '.%') + '.1'
如果您定义了parsename(numer,2)函数来获取第二个数字,则:

select @parm + '.' + (max(cast(parsename(nummer, 2) as int)) + 1) + '.1'
from tbArtikel 
where Nummer LIKE @parm + '.%'

一个相当直接的方法是使用(ab)拆分字符串以提取当前最大值。然后外部查询可以实现缺少值/9999/other的规则

值(此处为12)插入到表值构造函数中,以便能够使用
左连接检测缺少的值

SELECT CASE WHEN r.number IS NULL THEN 1001
            WHEN r.number = 9999 THEN 10001
            ELSE r.number + 1 END number
FROM ( VALUES(12) ) AS a(category)
LEFT JOIN (
  SELECT PARSENAME(prodno, 3) category,
         MAX(CAST(PARSENAME(prodno, 2) AS INT)) number
  FROM products
  GROUP BY PARSENAME(prodno, 3)
) r
ON r.category = a.category;


作为进一步的优化,您可以添加一个
,其中prodno类似于'12[。]%“
在内部查询中,不要分析不必要的行。

如果以固定宽度存储数字,格式会简单得多:000.000000.00000。您考虑过这一点吗?将3个部分存储在3个不同的字段中,并在视图中仅作为计算字段创建数字如何?这是客户要求的常规ID你知道,我不会对它有任何影响。我只需要实现主帖子中的正确分配。感谢这个查询正在工作,而且是最短的查询。无论如何,也感谢其他人!希望你的解决方案中没有隐藏的问题:)@Joachim Isaksson我还有一个问题,如果你不介意的话,我试着把参数传递给那个查询,然后做了一些错误的事情,就像总是得到1001一样-你能看看主帖子,告诉我哪里出了问题吗?@JohnDoe你不能不使用强制转换就将int参数用作字符串,你需要使用类似于
的强制转换(@producentNumber AS VARCHAR)+'[.]%'
将int参数转换为字符串。