接着上面IP地址字段查询问题,那就是统计结果的展示格式。朋友要的格式是:
城市1 城市2 城市3 城市4
2010-06 0 1 0 0
2010-08 0 1 0 2
2010-07 0 0 1 0
2010-05 1 0 0 0
时间和记录都是从SINO_USER查询出来的,而列名是从SINO_IP表中查询出来。本来用枚举法,直接把所有城市都用CASE
WHEN进行判断一遍就OK,但是,SINO_IP表中城市个数是不定的,就是说今天查询出来时4个城市,明天也许就是5个城市。这就需要我们的统计能支
持列的动态添加。我第一想到的是试图(VIEW),但是这个试图怎么写,才能保证动态生成列呢,这就要使用动态SQL,而动态SQL在哪里生成能,嘿嘿,
说了半天总算到正题了,没错,就是存储过程。可以使用存储过程动态生成VIEW,然后根据VIEW来查询。
1、数据基础
表结构我就不写了,和上篇博文一样的。
2、问题分析
select s.dd
,sum(city1) 城市1
,sum(city2) 城市2
,sum(city3) 城市3
,sum(city4) 城市4
,sum(city5) 城市5
from (select substr(to_char(t.update_time,'yyyy-mm-dd'),1,7) dd
,case when t1.city ='城市1' then 1 else 0 end city1
,case when t1.city ='城市2' then 1 else 0 end city2
,case when t1.city ='城市3' then 1 else 0 end city3
,case when t1.city ='城市4' then 1 else 0 end city4
,case when t1.city ='城市5' then 1 else 0 end city5
from sino_user t , sino_ip t1
where f_ip2number(t.ip) between f_ip2number(t1.ip_begin) and f_ip2number(t1.ip_end)) s group by s.dd
我们可以发现,SUM部分和CASE WHEN 部分都可以通过循环来添加,因此,我们可以把从城市对应IP段表中查询出来的数据存放在游标中,通过循环来生成统计SQL。
LET'S DO IT。
3、编写过程
create or replace procedure p_count is
v_sql dbms_sql.varchar2s;
l_cursor integer default dbms_sql.open_cursor;
l_rows number default 0;
i number default 2;
begin
v_sql(1) := 'create or replace view v_count as select s.dd';
for c_col in (select id,city from sino_ip order by id) loop
v_sql(i) := ',sum(city' ||c_col.id||') '||c_col.city;
i := i+1;
end loop;
v_sql(i) := 'from (select substr(to_char(t.update_time,''yyyy-mm-dd''),1,7) dd';
for c_col2 in (select id,city from sino_ip order by id) loop
v_sql(i+1) := ',case when t1.city ='''||c_col2.city||''' then 1 else 0 end city'|| c_col2.id;
i:= i + 1;
end loop;
v_sql(i+1) := 'from sino_user t , sino_ip t1 ';
v_sql(i+2) := 'where f_ip2number(t.ip) between f_ip2number(t1.ip_begin) and f_ip2number(t1.ip_end)) s group by s.dd';
dbms_sql.parse(c => l_cursor,statement => v_sql,lb =>
v_sql.first,ub => v_sql.last,lfflg => TRUE,language_flag =>
dbms_sql.native );
l_rows := dbms_sql.execute(l_cursor);
dbms_sql.close_cursor( l_cursor );
dbms_output.put_line(l_rows);
exception
when others then
dbms_output.put_line(sqlerrm);
end p_count;
大家可能注意到,我的在存储过程中用来存放动态SQL不是用VARCHAR2,用的是DBMS_SQL.VARCHAR2S,这是因为
VARCHAR2只能存放32K的字符,而我们的SQL是很长,将来会更长,因此使用DBMS_SQL.VARCHAR2分行来存储SQL。
同时,SQL的执行也不能使用EXECUTE IMMEDIATE,因为它也只能执行32K的SQL,我们使用DMBS_SQL.PARSE,通过游标来执行。
OK,执行。
报错了.....
没有足够的权限。
呵呵,我们在PL/SQL中创建视图需要创建视图的权限。
OK,我们给账号个CREATE ANY VIEW的权限。
执行
没报错。
我们来查询VIEW
select * from v_count t
结果出来了,和我上面写的要求一样。
那我们来验证它能不能动态生成列。
我们在SINO_IP插入城市5,一个新的IP段,然后在SINO_USER表中插入一条IP数据城市5的记录。再来查询:
城市1 城市2 城市3 城市4 城市5
2010-06 0 1 0 0 0
2010-08 0 1 0 2 0
2010-07 0 0 1 0 0
2010-05 1 0 0 0 1
OK,成功了。哈哈
分享到:
相关推荐
mysql中有种可以通过join相关操作进行表与表之间的方式查询不同结果集,但是在一对多的情况下,关键查询的结果是多条的.例如:班级和学习的关系,我想很直观的看到班级和学生的情况,列表显示出班级的信息和班级的男生...
1. SELECT语句:这是SQL中最基本的部分,用于指定你希望在查询结果中看到的列。例如,如果你有一个名为`employees`的表,你可以用`SELECT name, salary FROM employees`来获取所有员工的名字和薪水。 2. WHERE子句...
在MySQL数据库中,了解一个表包含多少个字段是非常重要的基础操作之一。这不仅有助于数据库管理员更好地管理数据结构,还能够帮助开发人员更准确地编写SQL查询语句。本文将详细介绍如何使用MySQL来查询表中的字段...
1. **数据迁移**:当需要将数据从一个数据库迁移到另一个数据库时,可以通过这种方式快速获取原数据库的表结构信息,以便在新数据库中创建相应的表结构。 2. **表结构分析**:开发人员在进行数据库设计或维护时,...
在实际工作中,我们经常会遇到需要将两张无关联表的数据列合并到一个结果集中的需求。这种操作可以帮助我们更好地组织数据,使得数据分析更加便捷高效。下面我们将详细探讨如何通过SQL语句来实现这一目标,并对相关...
在实际工作中,我们经常会遇到需要对数据表中的记录进行去重的情况,尤其是当某个字段作为唯一标识符时,我们希望能够基于这个字段获取最新的、唯一的或者汇总的数据记录。下面将详细阐述这一知识点。 ### SQL 去重...
接下来,我们需要设计一个动态表单,这通常涉及到HTML、JavaScript和CSS的配合。使用SpringMVC的ModelAndView,我们可以将后端数据绑定到视图模板,如JSP或Thymeleaf,生成动态的表单元素。JavaScript,如jQuery或...
1. 创建两个转换:一个用于获取表信息(方法1、方法2),另一个用于处理单个表并添加字段(方法1或方法2的子转换)。 2. 在获取表信息的转换中,使用`Table Input`查询源数据库中的表名,并通过`Filter Rows`和`...
在数据库管理中,有时我们需要在查询结果中添加一个序列号列,这可以帮助我们更好地组织数据,便于阅读和分析。在Access数据库中,可以利用SQL语言的内置函数来实现这一功能。Access是Microsoft Office套件的一部分...
1. **创建数据窗口对象**:首先,你需要创建一个基本的数据窗口对象,选择对应的数据库表或SQL查询作为数据源。 2. **获取数据窗口对象引用**:在代码中,通过`FindObject()`函数获取数据窗口对象的引用,以便于在...
在MySQL数据库中,有时我们需要将一个表中的某个字段的数据复制到另一个表的相应字段中,以满足特定的数据迁移或同步需求。以下是一些常见的SQL语句写法来实现这一目标。 1. **LEFT OUTER JOIN** 方法: ```sql ...
在SQL查询语言中,将指定的列作为标题列是一种数据透视技术的应用,这种技术主要用于将行数据转换为列数据,从而实现数据结构的重塑,便于数据分析和报告制作。这一过程通常被称为“列转行”或“透视”,在SQL中可以...
对于每个动态字段,创建一个`ParameterField`实例,设置其名称和值(这里使用`ParameterDiscreteValue`)。这些参数将被用在SQL查询中,使得查询能够根据参数动态改变。 8. **SQL查询构造**:在循环中,动态拼接SQL...
然后,创建一个动态SQL查询,将这些日期作为列名: ```sql SET @sql = NULL; SELECT GROUP_CONCAT( CONCAT( 'MAX(IF(sale_date = ''', sale_date, ''', quantity, NULL)) AS ', sale_date ) ) INTO @sql FROM ( ...
这些步骤允许我们对结果集进行迭代,每次迭代可以将一行数据作为参数传递给下一个转换。通过这种方式,我们可以根据每条记录执行个性化的数据处理操作。 在Kettle8.2中,这个过程可能如下: 1. **创建初始转换**:...
使用一个属性字段作为超链 在内容表中右击包含一个超链接字段的图层,然后点击properties ,单击Display选项卡。选中Supprt Hyper3. Hyperlinks using field选项,单击下拉箭头并点击一个字段。 单击Document or URL...
Oracle 10g数据库系统是Oracle公司发布的一个版本,提供了丰富的功能和强大的性能。在数据库管理中,有时候我们需要查找所有包含特定字段的表,这对于数据治理、数据分析或优化查询性能非常有帮助。以下是如何在...
这个模板是空白的,将作为我们后续添加动态字段的基础。 其次,创建一个记录集(DataSet)。在Visual Studio中,可以通过右键点击工程名,然后选择“添加” -> “新建项”,并选择“数据集”(DataSet)。在DataSet...
### MySQL 查询根据列按条件...- 最后一个查询计算`t2`表中`列1`的数量,并将结果与其他统计信息一起显示,这里的`列2`、`列3`等为空字符串。 通过这种方式,我们可以灵活地组合不同的查询来满足复杂的数据统计需求。
3. 子查询:在一个查询中嵌套另一个查询,用子查询的结果作为父查询的一部分。可以用于复杂条件的筛选或者获取多表关联的中间结果。 4. 数据透视表查询:将数据汇总并按照特定方式排列,用于数据分析。 四、易语言...