Oracle:如何只获取列中具有特定条件的行

时间:2016-09-12 15:01:34

标签: sql oracle

我有三个表,客户,订单和客户订单,如下所示:

Customers:
    ID   NAME
    1    Peter
    2    Jack
    3    Lisa

Orders:
    ID   INIT_DATE    END_DATE
    1    10-11-2014   10-11-2015
    2    23-11-2014   01-01-2015
    3    23-11-2014   03-05-2015
    4    04-04-2016   08-11-2016
    5    13-07-2016   01-11-2016
    6    04-06-2016   30-10-2016
    7    12-11-2014   01-05-2015
    8    26-11-2014   10-10-2015
    9    05-09-2016   11-11-2016

Customers_Orders:
   CUSTOMER_ID   ORDER_ID
   1             1
   1             2
   1             3
   2             4
   2             5
   2             6
   3             7
   3             8
   3             9

我需要让所有订单都过时的客户。我的意思是,那些sysdate的命令在init_date和end_date之间。在这种情况下,预期的结果是1-Peter。

我试过的是这个:

SELECT *
FROM Customers
WHERE
ID NOT IN (
  SELECT DISTINCT Customers_Orders.CUSTOMER_ID
  FROM Customers_Orders, Orders
  WHERE Customers_Orders.ORDER_ID = Orders.ID
  AND Orders.INIT_DATE <= SYSDATE AND Orders.END_DATE > SYSDATE
)

但我不喜欢“NOT IN”语法因为性能低下。还有另一种方式吗?

注意:日期格式为dd-mm-yyyy

编辑:我更正了问题(粗体)。

3 个答案:

答案 0 :(得分:2)

加入三个表并使用条件聚合来检查客户的所有订单是否都已过时。

select c.id,c.name
from customer_orders co
join orders o on o.id=co.order_id
join customers c on c.id=co.customer_id
group by c.id,c.name
having count(case when sysdate between co.init_date and co.end_date then 1 end) = 0

答案 1 :(得分:2)

这将排除INIT_DATE少于今天且END_DATE&gt;的所有客户。今天。

with Curr_ord as
(
select co1.customer_id, co1.order_id
from  customers_orders co1
inner join orders o1
on o1.id = co1.order_id
where o1.INIT_DATE <= sysdate
and o1.END_DATE > sysdate
)

select C1.*
from Customers C1
left join Curr_Ord CO2
on C1.Customer_ID = CO2.Customer_ID

where CO2.Customer_ID is null

答案 2 :(得分:-1)

为什么不加入?

  SELECT DISTINCT C.CUSTOMER_ID
    FROM customers c
       JOIN Customers_Orders co on co.customer_id = c.customer_id
       JOIN Orders od on od.order_id = co.order_id
    WHERE Od.INIT_DATE <= SYSDATE 
      AND Od.END_DATE > SYSDATE

通过对订单进行正确的索引,您可以通过将过滤器放入连接来获得性能提升:

  SELECT DISTINCT C.CUSTOMER_ID
    FROM customers c
       JOIN Customers_Orders co on co.customer_id = c.customer_id
       JOIN (SELECT od.order_id 
               from Orders 
               WHERE Od.INIT_DATE <= SYSDATE 
                 AND Od.END_DATE > SYSDATE )  od on od.order_id = co.order_id

但现在我们正在讨论性能调整策略....在这种情况下,我们需要讨论您的数据配置文件等以获得最佳解决方案。