Sql Case语句不支持查询中具有列名的水平搜索

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

我是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_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专家:)