到目前为止,我已经提出了以下内容:
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
答案 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提供的查询返回两行,这两行获得一行。