案例语句不支持在查询中使用列名进行水平搜索

时间:2016-01-06 17:13:56

标签: sql oracle

我是ORACLE SQL的新手,我正在努力学习它。 我有以下表格定义:

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;

我的目标如下: 1-针对每个saler_id搜索最高销售额和第二高销售额。 例如,在我们的上述情况中: 对于saler_id = 101,最高销售额为525,第二高销售额为255 与saler_id相似= 102最高销售额为55,第二高销售额为25

对于我的上述方法,我使用以下查询:

ORA-00932: inconsistent datatypes: expected NUMBER got CHAR
00932. 00000 -  "inconsistent datatypes: expected %s got %s"
*Cause:    
*Action:
Error at Line: 60 Column: 6

但我收到以下错误:

sympy

请指导我以下内容: 1-如何水平搜索数据以获得最大和最大秒数。 2-请指导我水平搜索行数据的替代方法。

4 个答案:

答案 0 :(得分:4)

获取最大值只是:

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;

答案 1 :(得分:1)

您遇到错误,因为在else部分中添加了字符串'new case found',其余的case语句处理了数字。 when和else子句中的数据类型应该匹配。 采用替代方法,您可以使用unpivot并将月销售数据分成一行,并使用分析函数获得第一高或第二高。

答案 2 :(得分:1)

正如其他人所说,问题是WHEN语句中的CASE子句返回INTEGER个值,但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;

祝你好运。

答案 3 :(得分:1)

您的数据模型错误 我要做的第一件事是使用此查询来取消数据:

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

上述查询将以这种格式给出结果:

 SALER_ID MON                VAL          X
---------- ----------- ---------- ----------
       101 FEB_SALES          525          1 
       101 MARCH_SALES        255          2 
       102 FEB_SALES           55          1 
       102 MARCH_SALES         25          2 
       103 JAN_SALES        45545          1 
       103 FEB_SALES         5125          2 

如果您有超过3个月的月份,则可以轻松扩展此查询以更改此部分:
val for mon in ( JAN_SALES,FEB_SALES,MARCH_SALES, April_sales, MAY_SALES, JUNE_SALES, JULY_SALES, ...... NOVEMBER_SALES, DECEMBER_SALES )

如果您想在一行中同时使用两个值,则需要将数据转回:

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" )
);

这会以这种形式给出结果:

  SALER_ID First value Second value
---------- ----------- ------------
       101         525          255 
       102          55           25 
       103       45545         5125 

编辑 - 为什么在PIVOT查询中使用MAX

简短的回答是:因为语法在这里要求聚合函数 请参阅此链接以获取语法:http://docs.oracle.com/cd/E11882_01/server.112/e41084/statements_10002.htm#CHDCEJJE enter image description here

更广泛的答案:
PIVOT条款只是一种语法糖,简化了一般的经典&#34;使用聚合函数和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

有关PIVOT查询的更多信息,您可以在网上找到,有很多关于枢轴查询如何工作的优秀解释。

上面的数据透视查询,用&#34;标准&#34; SQL,相当于这个Oracle的查询:

SELECT *
FROM table11
PIVOT (
  max(value) FOR some_column IN ( 'X', 'Y', 'Z' )
)

这些PIVOT查询转换如下记录:

        ID SOME_COLUMN      VALUE
---------- ----------- ----------
         1 X                  10 
         1 X                  15 
         1 Y                  20 
         1 Z                  30 

成为一个记录(对于每个id),如下所示:

        ID        'X'        'Y'        'Z'
---------- ---------- ---------- ----------
         1         15         20         30 

请注意,源表包含id = 1和some_column =&#39; X&#39;的两个值。 - &GT; PIVOT查询使用聚合函数来支持&#34;一般&#34; case,其中输出中的一条记录可能有许多源记录。在这个例子中,&#39; MAX&#39;函数用于选择更大的值15.
但是,PIVOT查询还支持您的特定情况,其中结果中的每个值只有一个源记录。