首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为查找表生成数字1-100的Oracle SQL select语句?

为查找表生成数字1-100的Oracle SQL select语句?
EN

Stack Overflow用户
提问于 2016-08-08 17:40:19
回答 4查看 811关注 0票数 0

我有一个查询,它按年龄组提取一些汇总的统计数据。

代码语言:javascript
运行
复制
    Agegroup    Freq
    0-5         2.3
    6-10        3.2
    11-15       3.6

由于各种原因,我需要输出数据作为以下格式中每一个年龄1-100岁的查找表

代码语言:javascript
运行
复制
    Age Agegroup    Freq
    1   0-5         2.3
    2   0-5         2.3
    3   0-5         2.3
    4   0-5         2.3
    5   0-5         2.3
    6   6-10        3.2
    7   6-10        3.2
    8   6-10        3.2
    9   6-10        3.2
    10  6-10        3.2
...

我怎么能继续这么做?我无法创建表,所以我在想,是否有一种方法可以编写一种select语句,该语句包含所有的年龄1-100岁和年龄组,然后将其加入到原始查询中,该查询具有按年龄组计算的频率--如下所示

代码语言:javascript
运行
复制
SELECT t1.age, [case when statemenet that assigns the correct age group from t1.Age] "Agegroup"

FROM ([statemement that generates numbers 1-100] "age") t1

JOIN (Original query that creates the aggreated agegroup data) t2 on t1.Agegroup = t2.Agegroup

所以我有两个问题

  1. 这是一种有意义的方法吗?
  2. 是否有可能生成我正在寻找的t1?即创建表单的t1的select语句 年龄组别1 0-5 2 0-5 3 0-5 4 0-5 5 6 6 6-10 7 6-10 8 6-10 9 6-10 6 ..。

它可以与按年龄组划分频率的查询相结合吗?

EN

回答 4

Stack Overflow用户

发布于 2016-08-08 18:20:45

就像这样..。我包括了0岁(如果需要的话可以排除它),我只读了15岁。这是硬编码的;只要做一点额外的工作,它就可以匹配范围内最高的年龄。

这个版本做了不必要的工作,因为它反复计算子字符串。它仍然可以在不到一秒钟的时间内执行,但是如果性能变得重要,就可以首先编写它来计算CTE中的那些子字符串,这样就不会重复计算它们。(此处未显示)

代码语言:javascript
运行
复制
with
     inputs (agegroup, freq ) as (
       select '0-5',   2.3 from dual union all
       select '6-10',  3.2 from dual union all
       select '11-15', 3.6 from dual
     )
select c.age, i.agegroup, i.freq
from   (select level - 1 as age from dual connect by level <= 16) c
       inner join inputs i
       on age between to_number(substr(i.agegroup, 1, instr(i.agegroup, '-') - 1))
              and     to_number(substr(i.agegroup, instr(i.agegroup, '-') + 1))
order by age
;

输出:

代码语言:javascript
运行
复制
 AGE AGEGROUP        FREQ
---- --------- ----------
   0 0-5              2.3
   1 0-5              2.3
   2 0-5              2.3
   3 0-5              2.3
   4 0-5              2.3
   5 0-5              2.3
   6 6-10             3.2
   7 6-10             3.2
   8 6-10             3.2
   9 6-10             3.2
  10 6-10             3.2
  11 11-15            3.6
  12 11-15            3.6
  13 11-15            3.6
  14 11-15            3.6
  15 11-15            3.6

16 rows selected.
票数 1
EN

Stack Overflow用户

发布于 2016-08-08 19:42:03

这里有一个不同的解决方案,使用分层查询。它不再需要“魔术数字”了,年龄是由范围逻辑决定的,并且没有连接(除了查询引擎在层次化查询的幕后所做的其他事情)。在您提供的非常小的示例中,优化器成本比我提供的基于连接的解决方案低20%,这可能会导致执行速度稍微快一些。

(注:我发布了两种不同的解决方案,因此我认为它们是不同的答案-而不是编辑我之前的文章。我不知道哪一种行动合适。)

还有一条要承认@AlexPoole在他的帖子中提到了这种方法;我直到现在才看到它,否则我会从一开始就承认它。

代码语言:javascript
运行
复制
with
     inputs (agegroup, freq ) as (
       select '0-5',   2.3 from dual union all
       select '6-10',  3.2 from dual union all
       select '11-15', 3.6 from dual
     )
select  to_number(substr(agegroup, 1, instr(agegroup, '-') - 1)) + level - 1 as age,
        agegroup, freq
from    inputs
connect by  level <= 1 + to_number(substr(agegroup, instr(agegroup, '-') + 1)) - 
                         to_number(substr(agegroup, 1, instr(agegroup, '-') - 1))  
        and prior agegroup = agegroup
        and prior sys_guid() is not null
order by age
;
票数 1
EN

Stack Overflow用户

发布于 2016-08-08 18:16:04

如果使用11 gR2或更高版本,另一种方法是使用带有正则表达式的递归子查询分解从字符串值中提取每个范围内的较低和较高年龄;

代码语言:javascript
运行
复制
with original_query (agegroup, freq) as (
  -- Original query that creates the aggreated agegroup data
  select '0-5', 2.3 from dual
  union all select '6-10', 3.2 from dual
  union all select '11-15', 3.6 from dual
),
r (age, agegroup, freq) as (
  select to_number(regexp_substr(agegroup, '\d+', 1, 1)), agegroup, freq
  from original_query
  union all
  select age + 1, agegroup, freq
  from r
  where age < to_number(regexp_substr(agegroup, '\d+', 1, 2))
)
select age, agegroup, freq
from r
order by age;

       AGE AGEGR       FREQ
---------- ----- ----------
         0 0-5          2.3
         1 0-5          2.3
         2 0-5          2.3
         3 0-5          2.3
         4 0-5          2.3
         5 0-5          2.3
         6 6-10         3.2
         7 6-10         3.2
         8 6-10         3.2
         9 6-10         3.2
        10 6-10         3.2
        11 11-15        3.6
        12 11-15        3.6
        13 11-15        3.6
        14 11-15        3.6
        15 11-15        3.6

锚成员从现有的结果集中获取每个原始行,并提取下限数字(0、6、11、.)使用一个简单的正则表达式--这也可以用substr/instr来完成。

递归成员会重复这些锚定行中的每一行,每次增加一行,直到达到范围的上限数为止。

您也可以使用connect by,但是对于多个源行,它会更尴尬一些。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38835399

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档