Oracle排序数据有3列条件

时间:2018-01-16 01:17:09

标签: sql oracle

我想在Oracle上按3列条件对数据进行排序。

需要ORDER BY DATEADDED,ARTICLEID_FK,BOX_SERIAL_NO

到目前为止,我在查询中要做的是:

SELECT DISTINCT
    S.FORM_NO,
    S.ARTICLEID_FK,
    S.BOX_SERIAL_NO,
    S.ACTUAL_WEIGHT,
    TO_CHAR(S.DATEADDED, 'DD-MON-YYYY HH24:MI:SS') AS DATEADDEDS,
    S.ADDEDBY,
    B.BOX_SERIAL_NO,
    B.ARTICLEID_FK,
    B.DATE_CODE
FROM 
    WA_LA_TBL_ARTICLES_SCAN S JOIN WA_LA_TBL_ARTICLES_BOX_SN B ON 
        S.BOX_SERIAL_NO = B.BOX_SERIAL_NO 
        AND TO_CHAR(S.DATEADDED, 'YYYY-MM-DD HH24:MI') BETWEEN 
              '2018-01-15 08:00' AND '2018-01-16 07:59'
ORDER BY S.ARTICLEID_FK ASC, B.BOX_SERIAL_NO ASC, S.DATEADDED DESC

当我运行该查询时,我收到了这个错误:

ORA-01791: not a SELECTed expression

错误指向S.DATEADDED DESC

逻辑是,首先需要按日期排序然后按文章ID排序,然后按顺序排序。

2 个答案:

答案 0 :(得分:2)

使用<heading> <hgroup> <h1>NERD</h1> <h1>CO.</h1> </hgroup> <nav> <ul> <li><a href="#">articles</a></li> <li><a href="#">podcast</a></li> <li><a href="#">social</a></li> <li><a href="#">about</a></li> <li><a href="#">contact</a></li> </ul> </nav> </heading>查询,您只能按所选列进行排序。因此,一个简单的解决方案是选择列。或者,使用select distinct

group by

注意:

  • 日期比较现在只使用日期算术。无需转换为字符串进行日期比较。
  • SELECT S.FORM_NO, S.ARTICLEID_FK, S.BOX_SERIAL_NO, S.ACTUAL_WEIGHT, TO_CHAR(S.DATEADDED, 'DD-MON-YYYY HH24:MI:SS') AS DATEADDEDS, S.ADDEDBY, B.BOX_SERIAL_NO, B.ARTICLEID_FK, B.DATE_CODE FROM WA_LA_TBL_ARTICLES_SCAN S JOIN WA_LA_TBL_ARTICLES_BOX_SN B ON S.BOX_SERIAL_NO = B.BOX_SERIAL_NO AND S.DATEADDED BETWEEN TIMESTAMP '2018-01-15 08:00:00' AND TIMESTAMP '2018-01-16 07:59:00' GROUP BY S.FORM_NO, S.ARTICLEID_FK, S.BOX_SERIAL_NO, S.ACTUAL_WEIGHT, TO_CHAR(S.DATEADDED, 'DD-MON-YYYY HH24:MI:SS'), S.ADDEDBY, B.BOX_SERIAL_NO, B.ARTICLEID_FK, B.DATE_CODE ORDER BY S.ARTICLEID_FK ASC, B.BOX_SERIAL_NO ASC, MAX(S.DATEADDED) DESC; 使用ORDER BY。这对你的目的应该没问题。
  • 您不希望MAX()字符串版本。格式错误,因为日期是第一天(字符串按字符串排序,而不是日期)。

答案 1 :(得分:1)

来自Oracle9i Database Error Messages

  

ORA-01791不是SELECTed表达式

     

原因: ORDER BY项目不正确。该查询是带有ORDER BY子句的SELECT DISTINCT查询。在此上下文中,所有ORDER BY项必须是常量,SELECT列表表达式或操作数为常量或SELECT列表表达式的表达式。

     

操作:从SELECT列表中删除不适当的ORDER BY项,然后重试该语句。

此select-distinct-query等同于以下逐个查询

SELECT DISTINCT
    S.FORM_NO,
    S.ARTICLEID_FK,
    S.BOX_SERIAL_NO,
    S.ACTUAL_WEIGHT,
    TO_CHAR(S.DATEADDED, 'DD-MON-YYYY HH24:MI:SS') AS DATEADDEDS,
    S.ADDEDBY,
    B.BOX_SERIAL_NO,
    B.ARTICLEID_FK,
    B.DATE_CODE
FROM 
    WA_LA_TBL_ARTICLES_SCAN S JOIN WA_LA_TBL_ARTICLES_BOX_SN B ON 
        S.BOX_SERIAL_NO = B.BOX_SERIAL_NO 
        AND TO_CHAR(S.DATEADDED, 'YYYY-MM-DD HH24:MI') BETWEEN 
              '2018-01-15 08:00' AND '2018-01-16 07:59'
ORDER BY S.ARTICLEID_FK ASC, B.BOX_SERIAL_NO ASC, S.DATEADDED DESC

此select-distinct-query等同于以下逐个查询:

SELECT 
    S.FORM_NO,
    S.ARTICLEID_FK,
    S.BOX_SERIAL_NO,
    S.ACTUAL_WEIGHT,
    TO_CHAR(S.DATEADDED, 'DD-MON-YYYY HH24:MI:SS') AS DATEADDEDS,
    S.ADDEDBY,
    B.BOX_SERIAL_NO,
    B.ARTICLEID_FK,
    B.DATE_CODE
FROM 
    WA_LA_TBL_ARTICLES_SCAN S JOIN WA_LA_TBL_ARTICLES_BOX_SN B ON 
        S.BOX_SERIAL_NO = B.BOX_SERIAL_NO 
        AND TO_CHAR(S.DATEADDED, 'YYYY-MM-DD HH24:MI') BETWEEN 
              '2018-01-15 08:00' AND '2018-01-16 07:59'
GROUP BY
    S.FORM_NO,
    S.ARTICLEID_FK,
    S.BOX_SERIAL_NO,
    S.ACTUAL_WEIGHT,
    TO_CHAR(S.DATEADDED, 'DD-MON-YYYY HH24:MI:SS') AS DATEADDEDS,
    S.ADDEDBY,
    B.BOX_SERIAL_NO,
    B.ARTICLEID_FK,
    B.DATE_CODE
ORDER BY S.ARTICLEID_FK ASC, B.BOX_SERIAL_NO ASC, S.DATEADDED DESC

现在很明显,Oracle必须提出这样的错误:一组数据的成员具有相同的TO_CHAR(S.DATEADDED,...) 但这并不保证相同的S.DATEADDED值。实际上,'YYYY-MM-DD HH24:MI:SS'的格式确实保证了这一点,但甲骨文没有进行如此深入的分析。如果使用函数,oracle会假设不同的参数可以导致相同的函数值。

因此,您可以通过将查询更改为以下内容来避免错误

SELECT 
    S.FORM_NO,
    S.ARTICLEID_FK,
    S.BOX_SERIAL_NO,
    S.ACTUAL_WEIGHT,
    TO_CHAR(S.DATEADDED, 'DD-MON-YYYY HH24:MI:SS') AS DATEADDEDS,
    S.ADDEDBY,
    B.BOX_SERIAL_NO,
    B.ARTICLEID_FK,
    B.DATE_CODE
FROM 
    WA_LA_TBL_ARTICLES_SCAN S JOIN WA_LA_TBL_ARTICLES_BOX_SN B ON 
        S.BOX_SERIAL_NO = B.BOX_SERIAL_NO 
        AND TO_CHAR(S.DATEADDED, 'YYYY-MM-DD HH24:MI') BETWEEN 
              '2018-01-15 08:00' AND '2018-01-16 07:59'
GROUP BY
    S.FORM_NO,
    S.ARTICLEID_FK,
    S.BOX_SERIAL_NO,
    S.ACTUAL_WEIGHT,
    S.DATEADDED,
    S.ADDEDBY,
    B.BOX_SERIAL_NO,
    B.ARTICLEID_FK,
    B.DATE_CODE
ORDER BY S.ARTICLEID_FK ASC, B.BOX_SERIAL_NO ASC, S.DATEADDED DESC

但请注意,有些事情很奇怪

你说你按日期排序然后是文章ID然后是Box Serial No'。事实并非如此,按文章ID排序,然后按Box序列号排序,然后按日期,

TO_CHAR(S.DATEADDED, 'YYYY-MM-DD HH24:MI') BETWEEN '2018-01-15 08:00' AND '2018-01-16 07:59'不是最佳选择。将函数应用于列值可能会阻止使用索引。所以你应该把这个子句重写为

 S.DATEADDED between TO_DATE('2018-01-15 08:00:00','YYYY-MM-DD HH24:MI:SS') and TO_DATE('2018-01-16 07:59:59','YYYY-MM-DD HH24:MI:SS')