Sql Case语句不支持查询中具有列名的水平搜索
我是ORACLE SQL的新手,正在努力快速学习。 我有以下表格定义:Sql Case语句不支持查询中具有列名的水平搜索,sql,oracle,Sql,Oracle,我是ORACLE SQL的新手,正在努力快速学习。 我有以下表格定义: Create table Sales_Biodata ( Saler_Id INTEGER NOT NULL UNIQUE, Jan_Sales INTEGER NOT NULL, Feb_Sales INTEGER NOT NULL, March_Sales INTEGER NOT NULL ); Insert into Sales_Biodata (SALER_ID,JAN_SALES,Feb_Sales,March
Create table Sales_Biodata
(
Saler_Id INTEGER NOT NULL UNIQUE,
Jan_Sales INTEGER NOT NULL,
Feb_Sales INTEGER NOT NULL,
March_Sales INTEGER NOT NULL
);
Insert into Sales_Biodata (SALER_ID,JAN_SALES,Feb_Sales,March_Sales)
values ('101',22,525,255);
Insert into Sales_Biodata (SALER_ID,JAN_SALES,Feb_Sales,March_Sales)
values ('102',22,55,25);
Insert into Sales_Biodata (SALER_ID,JAN_SALES,Feb_Sales,March_Sales)
values ('103',45545,5125,2865);
我的目标如下:
1-根据每个saler_id搜索最高销售额和第二高销售额。
例如,在我们上述案例中:
对于saler_id=101,最高销售额为525,次高销售额为255
与saler_id=102类似,最高销售额为55,次高销售额为25
对于我的上述方法,我使用以下查询:
Select Saler_Id,
(
CASE
WHEN JAN_SALES>FEB_SALES AND JAN_SALES>MARCH_SALES THEN JAN_SALES
WHEN FEB_SALES>JAN_SALES AND FEB_SALES>MARCH_SALES THEN FEB_SALES
WHEN MARCH_SALES>JAN_SALES AND MARCH_SALES>FEB_SALES THEN MARCH_SALES
WHEN JAN_SALES=FEB_SALES AND JAN_SALES=MARCH_SALES THEN JAN_SALES
WHEN JAN_SALES=FEB_SALES AND JAN_SALES>MARCH_SALES THEN JAN_SALES
WHEN JAN_SALES=MARCH_SALES AND JAN_SALES>FEB_SALES THEN JAN_SALES
WHEN FEB_SALES=JAN_SALES AND FEB_SALES>MARCH_SALES THEN FEB_SALES
WHEN FEB_SALES=MARCH_SALES AND FEB_SALES>JAN_SALES THEN FEB_SALES
WHEN MARCH_SALES=JAN_SALES AND MARCH_SALES>FEB_SALES THEN MARCH_SALES
WHEN MARCH_SALES=FEB_SALES AND MARCH_SALES>JAN_SALES THEN MARCH_SALES
ELSE 'NEW_CASE_FOUND'
END
) FIRST_HIGHEST,
(
CASE
WHEN JAN_SALES>FEB_SALES AND FEB_SALES>MARCH_SALES THEN FEB_SALES
WHEN FEB_SALES>JAN_SALES AND JAN_SALES>MARCH_SALES THEN JAN_SALES
WHEN JAN_SALES>MARCH_SALES AND MARCH_SALES>FEB_SALES THEN MARCH_SALES
ELSE 'NEW_CASE_FOUND'
END
) SECOND_HIGHEST
from
Sales_Biodata;
但我得到了以下错误:
ORA-00932: inconsistent datatypes: expected NUMBER got CHAR
00932. 00000 - "inconsistent datatypes: expected %s got %s"
*Cause:
*Action:
Error at Line: 60 Column: 6
请就以下事项向我提供指导:
1-如何水平搜索数据的最大值和第二个最大值。
2-请指导我水平搜索数据行的其他方法。您遇到了错误,因为字符串“new case found”添加在else部分,case语句的其余部分处理数字。when和else子句中的数据类型应匹配。
对于替代方法,您可以使用unpivot,将月份销售数据放在一行中,并使用分析函数获得第一最高值或第二最高值。获得最大值的方法很简单:
select greatest(jan_sales, feb_sales, mar_sales)
如果需要第二个值:
select (case when jan_sales = greatest(jan_sales, feb_sales, mar_sales)
then greatest(feb_sales, mar_sales)
when feb_sales = greatest(jan_sales, feb_sales, mar_sales)
then greatest(jan_sales, mar_sales)
else greatest(jan_sales, feb_sales)
end)
然而,这是解决整个问题的错误方法。主要问题是您的数据结构错误。将值存储在行而不是列中。因此,您需要取消绑定数据并重新聚合,例如:
select saler_id,
max(case when seqnum = 1 then sales end) as sales_1,
max(case when seqnum = 2 then sales end) as sales_2,
max(case when seqnum = 3 then sales end) as sales_3
from (select s.*, dense_rank() over (partition by saler_id order by sales desc) as seqnum
from (select saler_id, jan_sales as sales Sales_Biodata union all
select saler_id, feb_sales Sales_Biodata union all
select saler_id, mar_sales Sales_Biodata
) s
) s
group by saler_id;
正如其他人所说,问题在于
CASE
语句中的WHEN
子句返回整数
值,而ELSE
则返回字符串。我完全同意关于规范化的评论,但是如果您真的只想让这个查询工作,那么您需要将每个WHEN
子句的结果转换为字符,如下所示:
Select Saler_Id,
(
CASE
WHEN JAN_SALES>FEB_SALES AND JAN_SALES>MARCH_SALES THEN TO_CHAR(JAN_SALES)
WHEN FEB_SALES>JAN_SALES AND FEB_SALES>MARCH_SALES THEN TO_CHAR(FEB_SALES)
WHEN MARCH_SALES>JAN_SALES AND MARCH_SALES>FEB_SALES THEN TO_CHAR(MARCH_SALES)
WHEN JAN_SALES=FEB_SALES AND JAN_SALES=MARCH_SALES THEN TO_CHAR(JAN_SALES)
WHEN JAN_SALES=FEB_SALES AND JAN_SALES>MARCH_SALES THEN TO_CHAR(JAN_SALES)
WHEN JAN_SALES=MARCH_SALES AND JAN_SALES>FEB_SALES THEN TO_CHAR(JAN_SALES)
WHEN FEB_SALES=JAN_SALES AND FEB_SALES>MARCH_SALES THEN TO_CHAR(FEB_SALES)
WHEN FEB_SALES=MARCH_SALES AND FEB_SALES>JAN_SALES THEN TO_CHAR(FEB_SALES)
WHEN MARCH_SALES=JAN_SALES AND MARCH_SALES>FEB_SALES THEN TO_CHAR(MARCH_SALES)
WHEN MARCH_SALES=FEB_SALES AND MARCH_SALES>JAN_SALES THEN TO_CHAR(MARCH_SALES)
ELSE 'NEW_CASE_FOUND'
END
) FIRST_HIGHEST,
(
CASE
WHEN JAN_SALES>FEB_SALES AND FEB_SALES>MARCH_SALES THEN TO_CHAR(FEB_SALES)
WHEN FEB_SALES>JAN_SALES AND JAN_SALES>MARCH_SALES THEN TO_CHAR(JAN_SALES)
WHEN JAN_SALES>MARCH_SALES AND MARCH_SALES>FEB_SALES THEN TO_CHAR(MARCH_SALES)
ELSE 'NEW_CASE_FOUND'
END
) SECOND_HIGHEST
from
Sales_Biodata;
祝你好运。你的数据模型错了。
我要做的第一件事是使用以下查询取消PIVOT数据:
select * from sales_biodata
unpivot (
val for mon in ( JAN_SALES,FEB_SALES,MARCH_SALES )
)
;
在此之后,获得两个最高值相对容易:
SELECT *
FROM (
SELECT t.*,
dense_rank() over (partition by saler_id order by val desc ) x
FROM (
select * from sales_biodata
unpivot (
val for mon in ( JAN_SALES,FEB_SALES,MARCH_SALES )
)
) t
)
WHERE x <= 2
如果您有超过3个月的时间,您可以轻松扩展此查询更改此部分:1月销售、2月销售、3月销售、4月销售、5月销售、6月销售、7月销售、…11月销售、12月销售的周一val(1月销售、2月销售、3月销售、4月销售、5月销售、6月销售、7月销售)
如果希望在一行中同时包含两个值,则需要将数据转回到:
WITH src_data AS(
SELECT saler_id, val, x
FROM (
SELECT t.*,
dense_rank() over (partition by saler_id order by val desc ) x
FROM (
select * from sales_biodata
unpivot (
val for mon in ( JAN_SALES,FEB_SALES,MARCH_SALES )
)
) t
)
WHERE x <= 2
)
SELECT *
FROM src_data
PIVOT(
max(val) FOR x IN ( 1 As "First value", 2 As "Second value" )
);
编辑-为什么在透视查询中使用
MAX
简单的回答是:因为语法在这里需要一个聚合函数。
有关语法,请参见此链接:
更广泛的回答:
PIVOT子句只是一个语法糖,它简化了使用聚合函数和
GROUP BY
子句的一般“经典”PIVOT查询,如下所示:
SELECT id,
max( CASE WHEN some_column = 'X' THEN value END ) As x,
max( CASE WHEN some_column = 'Y' THEN value END ) As y,
max( CASE WHEN some_column = 'Z' THEN value END ) As z
FROM table11
GROUP BY id
ID SOME_COLUMN VALUE
---------- ----------- ----------
1 X 10
1 X 15
1 Y 20
1 Z 30
ID 'X' 'Y' 'Z'
---------- ---------- ---------- ----------
1 15 20 30
有关PIVOT查询的更多信息,您可以在网上找到,这里有很多关于PIVOT查询工作原理的精彩解释。上述pivot查询是用“标准”SQL编写的,相当于此Oracle查询:
SELECT *
FROM table11
PIVOT (
max(value) FOR some_column IN ( 'X', 'Y', 'Z' )
)
这些PIVOT查询可以这样转换记录:
SELECT id,
max( CASE WHEN some_column = 'X' THEN value END ) As x,
max( CASE WHEN some_column = 'Y' THEN value END ) As y,
max( CASE WHEN some_column = 'Z' THEN value END ) As z
FROM table11
GROUP BY id
ID SOME_COLUMN VALUE
---------- ----------- ----------
1 X 10
1 X 15
1 Y 20
1 Z 30
ID 'X' 'Y' 'Z'
---------- ---------- ---------- ----------
1 15 20 30
放入一个记录(对于每个id
),如下所示:
SELECT id,
max( CASE WHEN some_column = 'X' THEN value END ) As x,
max( CASE WHEN some_column = 'Y' THEN value END ) As y,
max( CASE WHEN some_column = 'Z' THEN value END ) As z
FROM table11
GROUP BY id
ID SOME_COLUMN VALUE
---------- ----------- ----------
1 X 10
1 X 15
1 Y 20
1 Z 30
ID 'X' 'Y' 'Z'
---------- ---------- ---------- ----------
1 15 20 30
请注意,源表包含两个id=1的值和一些_column='X'->10和15。PIVOT查询使用聚合函数来支持“常规”情况,即输出中的一条记录可能有多个源记录。在本例中,“MAX”函数用于选择更大的值15。但是,PIVOT查询也支持您的特定情况,即结果中的每个值只有一个源记录。查看您的
ELSE
。它是一根绳子。您还需要将其他值转换为字符串,可能需要使用to_char()
@GordonLinoff您的意思是to_char()
?吹毛求疵:Saler\u Id
如果您是SQL(和关系数据库)新手,可能应该是Seller\u Id
然后,我强烈建议您考虑规范化。如果您将数据模型更改为具有seller\u id、sales\u month、sales\u value
的表,则这将简单得多,因此每个销售员每月一行。需要问问自己的是,如何存储超过一年的数据,或者如何处理其他更复杂的查询。(您可能确实从理解中受益)。您的第三个查询非常复杂,我无法理解seqnum是什么,以及为什么您有max函数,并且您在子查询中使用了subquery,我正在尝试理解它,但您能否解释seqnum和max的用途(seqnum=1时的情况…)a littlethanks:)这是一个非常好的查询,我将尝试理解您查询的概念和逻辑,目前我没有15分,因此我无法提高投票率,但我将在收到该点后提高投票率。接受你的回答:)你能不能给我解释一下x IN的语句max(val)(1为“第一个值”,2为“第二个值”)你的查询,比如1-占位符1为“第一个值”,2为“第二个值”,我很清楚,你把所有密集秩1都作为第一个值,等等,但你为什么使用max(val)??我在答案中添加了一个解释,解释了为什么在pivot查询中使用“MAX”。谢谢:)你的解释让我终生理解了这个概念:)谢谢,我将在未来几年努力成为oracle专家:)