【问题标题】:Splitting data from one record is a specific column T-SQL从一条记录中拆分数据是特定列 T-SQL
【发布时间】:2018-03-16 08:06:10
【问题描述】:

我正在处理从 Oracle 导入 SQL Server 2012 的旧旧数据库。我有一个名为INSOrders 的表,其中包括一个名为OrderID 的列,类型为varchar(8)

插入数据的一个例子是:

A04-05  |  B81-02  |  C02-01
A01-01  |  B95-01  |  C99-05
A02-02  |  B06-07  |  C03-02
A98-06  |  B10-01  |  C17-01
A78-07  |  B02-03  |  C15-03
A79-01  |  B02-01  |  C78-06

第一个字母 = 订单类型,接下来的 2 位数字 = 年份 - 最后 2 位数字 = 该年份内的 OrderNum。

所以我将所有数据分成 3 列:(未存储,仅显示)

select 
    orderid,
    substring(orderid, 0, patindex('%[0-9]%', orderid)) as ordtype,
    right(max(datepart(yyyy, '01/01/' + substring(orderid, patindex('%[0-9]-%', orderid) - 1, 2))),2) as year,
    max(substring(orderid, patindex('%-[0-9]%', orderid) + 1, 2)) as ordnum
from 
    ins.insorders
where 
    orderid is not null
group by 
    substring(orderid, 0, patindex('%[0-9]%', orderid)), orderid
order by 
    ordtype

它看起来像这样:

OrderID  |  OrderType  |  OrderYear  | OrderNum
---------+-------------+-------------+----------
A04-05   |  A          |  04         |  05
A01-01   |  A          |  01         |  01
B10-03   |  B          |  10         |  03
B95-01   |  B          |  95         |  01
etc....

但现在我只想为所有OrderType 选择最大值:仅显示字母 A 的最大值,显示字母 B 的最大值等。我的意思是 Max,我的意思是来自 Letter AI 需要显示最近的年份和最新的订单号。所以如果我有 A04-01 和 A04-02 就显示 A04-02。

如果我能看到以下内容,我需要修改我的查询:

OrderID  |  OrderType  |  OrderYear  | OrderNum
---------+-------------+-------------+----------
A04-05   |  A          |  04         |  05
B10-03   |  B          |  10         |  03
C17-01   |  C          |  17         |  01

谢谢您,我将非常感谢您的帮助。

【问题讨论】:

  • 这有点奇怪,所以我假设 B10-03 OrderYear 显示 10 而不是 95 因为 10 表示为 201095 表示为1995?
  • 这不是像使用 MAX(orderid) 并从 group by 中删除 orderid 一样简单吗?

标签: sql-server function split substring max


【解决方案1】:

你可以试试下面的。使用您的原始查询作为 cte,并根据订单年份和订单号为每组订单类型分配行号。然后获取所有第 1 行,这应该是每个订单类型的最大值。

这一点DATEPART(yyyy,('01/01/' + OrderYear)) 将确保我们得到正确的年份,因此 95 是 1995 年,10 是 2010 年等等。

   ;WITH cte 
    AS (
    select orderid,
    substring(orderid, 0, patindex('%[0-9]%', orderid)) as ordtype,
    right(max(datepart(yyyy,'01/01/' + substring(orderid, patindex('%[0-9]-%', orderid) - 1, 2))),2) as year,
    max(substring(orderid, patindex('%-[0-9]%', orderid) + 1, 2)) as ordnum
    from ins.insorders
    where orderid is not null
    group by substring(orderid, 0, patindex('%[0-9]%', orderid)), orderid
    )

SELECT *
FROM
  (SELECT 
        *
      , ROW_NUMBER() OVER (PARTITION BY OrderType ORDER BY DATEPART(yyyy,('01/01/' + OrderYear)) DESC, OrderNum DESC) AS RowNum
    FROM cte) t
WHERE t.RowNum = 1

【讨论】:

    【解决方案2】:

    数据表现不佳,我只有一种方法可以“解决”它,我们需要做出很多假设:

    with cte_example
    as
    ( your query )
    select OrderID
           ,OrderType
           ,OrderYear
           ,OrderNum
    from
    (select *, row_number() over(partition by OrderType order by OrderYear DESC) rn      
    from cte_example
    where OrderYear <= right(year(getdate()),2)) t1
    where t1.rn = 1
    

    由于您已经有一个提取信息的查询,因此我不会费心更改它。我们将您的查询包装在 CTE 中,从中查询并应用row_number 函数来确定哪个OrderType 具有最新的OrderYear,以及它的OrderNumOrderID

    现在棘手的部分是年份的代表性很差(假设我对您原始帖子的评论是正确的),然后对OrderType B 使用任何类型的聚合将返回95,因为它在数字上是最大的。

    我们假设没有订单日期会超过本年度,任何订单日期都在 90 年代,使用以下语句:where OrderYear &lt; right(year(getdate()),2)。换句话说,得到今年和它的两个正确的字符。首先从getdate 中检索2017,然后使用RIGHT 函数检索17。我很确定为什么您会看到这很危险,因为如果您最近的日期是 1999 年呢?

    因此,通过过滤掉它们,我们可以看到每个 OrderType 的最新年份...希望这会有所帮助。

    Here 是我构建的 rextester 测试,用于处理您的查询,以防您想尝试。

    【讨论】:

      【解决方案3】:

      我认为您的原始查询几乎正是您所需要的,只是您需要使用 MAX(OrderID) 而不是按它分组。

      declare @Something table
      (
          orderid varchar(6)
      )
      
      insert @Something
      (
          orderid
      ) values
      ('A04-05'), ('B81-02'), ('C02-01'),
      ('A01-01'), ('B95-01'), ('C99-05'),
      ('A02-02'), ('B06-07'), ('C03-02'),
      ('A98-06'), ('B10-01'), ('C17-01'),
      ('A78-07'), ('B02-03'), ('C15-03'),
      ('A79-01'), ('B02-01'), ('C78-06')
      
      select max(orderid),
      substring(orderid, 0, patindex('%[0-9]%', orderid)) as ordtype,
      right(max(datepart(yyyy,'01/01/' + substring(orderid, patindex('%[0-9]-%', orderid) - 1, 2))),2) as year,
      max(substring(orderid, patindex('%-[0-9]%', orderid) + 1, 2)) as ordnum
      from myTable
      where orderid is not null
      group by substring(orderid, 0, patindex('%[0-9]%', orderid))
      order by ordtype
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-08-18
        • 1970-01-01
        • 2022-12-05
        • 2020-09-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多