如何从oracle中的多个表中获取值,包括日期

Posted

技术标签:

【中文标题】如何从oracle中的多个表中获取值,包括日期【英文标题】:how to get value from multiple table in oracle including date 【发布时间】:2018-01-19 10:38:22 【问题描述】:

我有三个表customers、orders和orderitems

客户表

CUSTOMER#   LASTNAME    FIRSTNAME
1001    MORALES BONITA
1002    THOMPSON    RYAN
1003    SMITH   LEILA
1004    PIERSON THOMAS
1005    GIRARD  CINDY
1006    CRUZ    MESHIA
1007    GIANA   TAMMY

订单表

ORDER#  CUSTOMER#   ORDERDATE
1000    1005    31/MAR/09
1001    1010    31/MAR/09
1002    1011    31/MAR/09
1003    1001    01/APR/09
1004    1020    01/APR/09

订单项表

ORDER#  ITEM#   ISBN    QUANTITY
1000    1   3437212490  1
1001    1   9247381001  1
1001    2   2491748320  1
1002    1   8843172113  2
1003    1   8843172113  1
1003    2   1059831198  1

我想为所有在 3 月份下过至少一个订单的客户打印客户姓名和客户下的订单总数。

我尝试了以下查询。我坚持这个问题。我在为 3 月至少下过一份订单的客户添加数量时遇到问题。

select c.firstname
, c.lastname
, or.orderitems# 
from customers c
, orderitems or
where customer# in 
(
    select customer# 
    from orders
    where order# in 
    (
        select order# 
        from orderitems 
        where /* (query truncated) */

【问题讨论】:

为什么这个查询需要 Orderitems 表? 查找项数 您说“我想为所有在 3 月份至少下过一个订单的客户打印客户姓名和客户下的订单总数。”因此,您需要客户和订单,仅此而已。您能否发布该示例数据所需的结果? 它就像:Girard cindy 在 3 月只下了一个订单,所以只需打印 1。如果其他客户下的订单超过 1 件,则必须添加所有项目 NAME ITEM 1. Girrad Cindy 1 【参考方案1】:

我想为所有在 3 月份下过至少一个订单的客户打印客户姓名和客户下的订单总数。

您不需要OrderItems 表。所以你可以这样做:

select c.lastname, c.firstname, count(*)
from customers c join
     orders o
     on c.CUSTOMER# = o.CUSTOMER#
group by c.lastname, c.firstname
having sum(case when orderdate >= date '2009-03-01' and orderdate < date '2009-04-01'
                then 1 else 0
           end) > 0;

您也可以在聚合之前进行过滤,使用exists(或in):

select c.lastname, c.firstname, count(*)
from customers c join
     orders o
     on c.CUSTOMER# = o.CUSTOMER#
where exists (select 1
              from orders o2
              where c.CUSTOMER# = o2.CUSTOMER# and
                    o2.orderdate >= date '2009-03-01' and
                    o2.orderdate <  date '2009-04-01'
             )
group by c.lastname, c.firstname

虽然我喜欢having 方法,但在聚合之前进行过滤通常效果更好。

【讨论】:

虽然问题不是很清楚,但 OP 似乎需要数量的总和,而不是订单的数量,如问题中所述 @WilliamRobertson 。 . .谢谢。【参考方案2】:

如果我理解得很好,您可能需要这样的东西(假设您的日期值没有时间信息):

select LASTNAME, FIRSTNAME, sum(QUANTITY)
from customers
       inner join Orders using(CUSTOMER#)
       inner join Orderitems using(ORDER#)  
group by LASTNAME, FIRSTNAME
having count(
             case when ORDERDATE between date '2009-03-01'
                                     and date '2009-03-31'
                  then 1 
             end
            ) > 0       

在这里,我应用having 条件以仅让客户在 3 月份至少有一个订单。 例如:

SQL> with customers(CUSTOMER#,   LASTNAME,    FIRSTNAME) as
  2  (
  3      select 1001, 'MORALES' , 'BONITA' from dual union all
  4      select 1002, 'THOMPSON', 'RYAN' from dual union all
  5      select 1003, 'SMITH'   , 'LEILA' from dual union all
  6      select 1004, 'PIERSON' , 'THOMAS' from dual union all
  7      select 1005, 'GIRARD'  , 'CINDY' from dual union all
  8      select 1006, 'CRUZ'    , 'MESHIA' from dual union all
  9      select 1007, 'GIANA'   , 'TAMMY' from dual
 10  ),
 11   Orders(ORDER#,  CUSTOMER#,   ORDERDATE) as
 12  (
 13      select 1000, 1005, to_date('31/MAR/09', 'DD/MON/YY') from dual union all
 14      select 1001, 1010, to_date('31/MAR/09', 'DD/MON/YY') from dual union all
 15      select 1002, 1011, to_date('31/MAR/09', 'DD/MON/YY') from dual union all
 16      select 1003, 1001, to_date('01/APR/09', 'DD/MON/YY') from dual union all
 17      select 1004, 1020, to_date('01/APR/09', 'DD/MON/YY') from dual
 18  ),
 19   Orderitems(ORDER#,  ITEM#,   ISBN,    QUANTITY) as
 20  (
 21      select 1000, 1, 3437212490, 1 from dual union all
 22      select 1001, 1, 9247381001, 1 from dual union all
 23      select 1001, 2, 2491748320, 1 from dual union all
 24      select 1002, 1, 8843172113, 2 from dual union all
 25      select 1003, 1, 8843172113, 1 from dual union all
 26      select 1003, 2, 1059831198, 1 from dual
 27  )
 28  select LASTNAME, FIRSTNAME, sum(QUANTITY)
 29  from customers
 30         inner join Orders using(CUSTOMER#)
 31         inner join Orderitems using(ORDER#)
 32  group by LASTNAME, FIRSTNAME
 33  having count(case when ORDERDATE between date '2009-03-01' and date '2009-03-31' then 1 end) > 0;

LASTNAME FIRSTN SUM(QUANTITY)
-------- ------ -------------
GIRARD   CINDY              1

SQL>

【讨论】:

【参考方案3】:

试试这个

select c.FIRSTNAME , c.LASTNAME , count(i.quantity)
from Customer c , Orders o , Orderitems i
where c.CUSTOMER# = o.CUSTOMER#
and o.ORDER# = i.ORDER#
and o.ORDERDATE between '01-mar-2018' and '30-mar-2018'
group by c.FIRSTNAME , c.LASTNAME;

【讨论】:

不错的答案;尽管您的 group by 列与您的非聚合 select atm 不一致(即代码不太有效)。 count 将计算出现次数,而不是总和。以这种方式使用日期是危险的,可能不起作用。这将获得 3 月份的订单数量(最多 30 个......),但对于在 3 月份下订单的用户,OP 似乎需要所有订单的总数。此外,最好切换到 ANSI 连接语法。

以上是关于如何从oracle中的多个表中获取值,包括日期的主要内容,如果未能解决你的问题,请参考以下文章

SQL ORACLE 从多个日期时间行中获取周数

从 Oracle Apex 页面获取多个值并将其存储在表中

如何从单个日期列-oracle 获取开始/结束日期

如何使用会话ID从php mysql中的两个或多个表中获取值

如何从多个表 Oracle 中获取最后两个最大日期

当嵌套表属于记录类型时,如何将数据填充到 Oracle 中的嵌套表中