可以使用WHERE子句的多个extract()?

时间:2014-09-05 11:10:49

标签: date

到目前为止,我已经提出了以下内容:

WHERE (extract(month FROM orders)) = 
                     (SELECT min(extract(month from orderdate))
                     FROM orders)

然而,这将因此返回零到多行,在我的情况下,很多,因为许多订单存在于同一个最早(最小)月份,即2月4日,2月9日,2月15日,...

我知道WHERE子句可以包含多个列,为什么以下不起作用?

WHERE (extract(day FROM orderdate)), (extract(month FROM orderdate)) = 
                     (SELECT min(extract(day from orderdate)), min(extract(month FROM orderdate))
                     FROM orders)

我只是得到:SQL Error: ORA-00920: invalid relational operator

任何帮助都会很棒,谢谢!

示例数据: 02 - 2012 14 - 2月 - 2012 22日 - 12月2012 09 - 2月 - 2013 18-JUL-2013 01-JAN-2014

输出: 02 - 2012 14-FEB-2012

期望的输出: 02 - 2012

3 个答案:

答案 0 :(得分:2)

我重新创建了你的桌子,发现你只是把括号搞砸了。以下适用于我:

where
    (extract(day from OrderDate),extract(month from OrderDate))
    =
    (select
        min(extract(day from OrderDate)),
        min(extract(month from OrderDate))
     from orders
    )

答案 1 :(得分:0)

使用类似的东西:

with cte1 as (
    select
        extract(month from OrderDate) date_month,
        extract(day from OrderDate) date_day,
        OrderNo
    from tablename
), cte2 as (
    select min(date_month) min_date_month, min(date_day) min_date_day
    from cte1
)
select cte1.*
from cte1
where (date_month, date_day) = (select min_date_month, min_date_day from cte2)

通用表格表达式使您可以重新构建数据,然后使用此数据进行选择。第一个cte-block(cte1)选择每个表行的月份和日期。然后Cte2选择min(月)和min(日期)。最后一个选择然后组合两个ctes以从cte1中选择具有所需月份和日期的所有行。

可能有一个较短的解决方案,但我喜欢常见的表表达式,因为它们几乎总是比“最佳,最短”的查询更好地理解。

答案 2 :(得分:0)

如果这真的是你想要的,就像看起来一样奇怪,那么作为一种不同的方法,你可以忘记提取和子查询对表来获得最小值,并使用分析方法代替:

select orderdate
from (
  select o.*,
    row_number() over (order by to_char(orderdate, 'MMDD')) as rn
  from orders o
)
where rn = 1;

ORDERDATE
---------
01-JAN-14 

row_number()根据订单日期中的月份和日期,有效地将伪列添加到原始表中的每一行。 rn值是唯一的,因此将有一行标记为1,这将是从最早月份的最早日期开始。如果您有相同日期/月份的多个订单,例如2013年1月1日和2014年1月1日,那么您仍然只能获得rn = 1的一个订单,但选择的订单是不确定的。您需要添加更多order by条件才能使其具有确定性,但我不知道您可能想要什么。

这是在内部查询中完成的;外部查询然后进行过滤,以便只返回标有rn = 1的记录;所以你从整个查询中得到一行。

这也避免了最早的一天数不在最早的月份数的情况 - 比如你只有2014年1月1日和2014年2月2日;分别比较日期和月份将查找2014年2月1日,但不存在。

SQL Fiddle(托马斯·特塞尔尼希(Thomas Tschernich)的抨击也是如此,给出了相同的数据结果)。


要将结果与发票表相关联,您不需要再次加入订单表 - 特别是不能使用交叉联接,这会使结果出现偏差。您可以通过两种方式进行连接:

SELECT 
    o.orderno,
        to_char(o.orderdate, 'DD-MM-YYYY'),
    i.invno
FROM 
  (
    SELECT o.*,
        row_number() over (order by to_char(orderdate, 'MMDD')) as rn
    FROM orders o
  ) o, invoices i
WHERE i.invno = o.invno
AND rn = 1;

或者:

SELECT 
    o.orderno,
        to_char(o.orderdate, 'DD-MM-YYYY'),
    i.invno
FROM 
  (
    SELECT orderno, orderdate, invno
    FROM
      (
        SELECT o.*,
            row_number() over (order by to_char(orderdate, 'MMDD')) as rn
        FROM orders o
      )
    WHERE rn = 1
  ) o, invoices i
WHERE i.invno = o.invno;

第一种看起来更有用,但执行计划是相同的。

SQL Fiddle使用您的pastebin提供的查询返回两行,这两行获得一行。