重写Max函数以允许字符串SQL?

重写Max函数以允许字符串SQL?,sql,oracle,Sql,Oracle,您好,我觉得这是一个简单的问题,但无法解决。我试图找到与另一列相关的最大值并将其分组,出现的问题是其中一个值是字符串 Name Value Nate 0 Nate 1 Jeff 2 Nate 2 Nate 'Test' 对于数据,我希望'Test'等于1。但是,如果我在这里使用MAX()函数,我将得到: Name Value Nate 'Test' Jeff 2 我只能想,如果我把“Test”读作1,然后使用max函数(我不知道怎么做),

您好,我觉得这是一个简单的问题,但无法解决。我试图找到与另一列相关的最大值并将其分组,出现的问题是其中一个值是字符串

Name    Value
Nate    0
Nate    1
Jeff    2
Nate    2
Nate    'Test'
对于数据,我希望'Test'等于1。但是,如果我在这里使用MAX()函数,我将得到:

Name    Value
Nate    'Test'
Jeff    2
我只能想,如果我把“Test”读作1,然后使用max函数(我不知道怎么做),或者可能会以某种方式将max()重载到我自己的定义中


感谢您提供的帮助。

在字符串列中存储混合数据通常是个坏主意

可以使用大小写表达式将特定字符串转换为固定值:

select max(case when value = 'Test' then '1' else value end) from ...
但您仍在处理字符串,因此您可能希望将其转换为数字,以防止在“2”之前进行“10”排序,例如:

select max(to_number(case when value = 'Test' then '1' else value end)) from ...

对样本数据使用CTE:

-- CTE for dummy data
with your_table (name, value) as (
  select 'Nate', '0' from dual
  union all select 'Nate', '1' from dual
  union all select 'Jeff', '2' from dual
  union all select 'Nate', '2' from dual
  union all select 'Nate', 'Test' from dual
)
-- actual query
select name,
  max(case when value = 'Test' then 1 else to_number(value) end) as value
from your_table
group by name;

NAME      VALUE
---- ----------
Nate          2
Jeff          2
但是您必须覆盖所有不能显式或隐式转换为数字的值

如果希望忽略非数值,或者将它们都视为相同的固定值,而不是将单个字符串映射到它们自己的数值,则If将稍微容易一些。然后,您可以编写一个函数,尝试转换任何字符串,如果它得到任何异常,则返回null(或其他固定值)

从12cR1开始,您甚至可以使用而不是永久性的独立或打包功能,如果这是偶然的事情:

with
  function hack_to_number(string varchar2) return number is
  begin
    return to_number(string);
  exception
    when others then
      return 1;
  end;
select name,
  max(hack_to_number(value)) as value
from your_table
group by name;

NAME      VALUE
---- ----------
Nate          2
Jeff          2
您最好回去重新设计数据模型,通过使用正确的数据类型来防止此类问题


正如@DrYWit在一篇评论中指出的,从12cR2开始,你甚至不需要这样做,就像内置的一样,如果你明确地称它为:

select name,
  max(to_number(value default 1 on conversion error)) as value
from your_table
group by name;

在字符串列中存储混合数据通常是个坏主意

可以使用大小写表达式将特定字符串转换为固定值:

select max(case when value = 'Test' then '1' else value end) from ...
但您仍在处理字符串,因此您可能希望将其转换为数字,以防止在“2”之前进行“10”排序,例如:

select max(to_number(case when value = 'Test' then '1' else value end)) from ...

对样本数据使用CTE:

-- CTE for dummy data
with your_table (name, value) as (
  select 'Nate', '0' from dual
  union all select 'Nate', '1' from dual
  union all select 'Jeff', '2' from dual
  union all select 'Nate', '2' from dual
  union all select 'Nate', 'Test' from dual
)
-- actual query
select name,
  max(case when value = 'Test' then 1 else to_number(value) end) as value
from your_table
group by name;

NAME      VALUE
---- ----------
Nate          2
Jeff          2
但是您必须覆盖所有不能显式或隐式转换为数字的值

如果希望忽略非数值,或者将它们都视为相同的固定值,而不是将单个字符串映射到它们自己的数值,则If将稍微容易一些。然后,您可以编写一个函数,尝试转换任何字符串,如果它得到任何异常,则返回null(或其他固定值)

从12cR1开始,您甚至可以使用而不是永久性的独立或打包功能,如果这是偶然的事情:

with
  function hack_to_number(string varchar2) return number is
  begin
    return to_number(string);
  exception
    when others then
      return 1;
  end;
select name,
  max(hack_to_number(value)) as value
from your_table
group by name;

NAME      VALUE
---- ----------
Nate          2
Jeff          2
您最好回去重新设计数据模型,通过使用正确的数据类型来防止此类问题


正如@DrYWit在一篇评论中指出的,从12cR2开始,你甚至不需要这样做,就像内置的一样,如果你明确地称它为:

select name,
  max(to_number(value default 1 on conversion error)) as value
from your_table
group by name;

这个正则表达式“把戏”怎么样


这个正则表达式“把戏”怎么样


value
的数据类型是什么?其中一个值不能是字符串;该列中的所有值都是字符串-有些恰好只由数字组成。在
Test
周围显示单引号有点混乱(除非字符串值实际上也包含单引号)。根据这些数据,你大概期望Nate的最大值也是2?这是唯一的非数字值吗?所有的数字都是单个数字吗?值的数据类型是什么??其中一个值不能是字符串;该列中的所有值都是字符串-有些恰好只由数字组成。在
Test
周围显示单引号有点混乱(除非字符串值实际上也包含单引号)。根据这些数据,你大概期望Nate的最大值也是2?这是唯一的非数字值吗?所有的数字都是个位数吗?因为12c版本2,您可以使用“转换错误时”参数,例如to_number('test'默认值1 on conversion error)。是的,我一开始就照您说的做了,我遇到的问题是我还想要MAX()根据结果表示特定的日期字段。我坚持使用case语句,只需过滤前端应用程序上的数据。至于数据结构,我同意,但无法控制:/。谢谢你的快速回复。我喜欢那个带有转换错误的修复程序,也许可以改为这样做。非常感谢。由于12c release 2,您可以使用“on conversion error”参数,例如to_number(“test”默认值为1 on conversion error)。是的,我一开始就照您说的做了,我遇到的问题是,我还希望MAX()表示基于结果的特定日期字段。我坚持使用case语句,只需过滤前端应用程序上的数据。至于数据结构,我同意,但无法控制:/。谢谢你的快速回复。我喜欢那个带有转换错误的修复程序,也许可以改为这样做。非常感谢。