复杂的Oracle Query没有返回正确的信息

时间:2014-10-27 22:55:34

标签: sql oracle oracle11g subquery

这是问题的一个更直接的部分。以下查询有问题。它返回客户使用的每个ip_address,而不是过滤当前月份。当deallocation_date为null或者日期之间是唯一需要选择的IP地址时。这里直接下面的查询是我尝试使用相关子查询,如果它存在于这些条件计数内,并且这些IP地址的总和。但是,我在下面显示只有29个Ip地址,deallocation_date = null并且在这些日期之间取消分配,因为对于此客户,最大释放日期是八月。我知道它选择了所有已分配给客户的IP。请帮我修复子查询以返回正确的数据。我不太了解SQL,知道我的错误在哪里。我知道它与我使用的方式有关。

我也知道,因为有人指出它只会在本月最后一天的00:00:00之前选择,现在我可以稍后解决这个问题。我需要它来返回正确的数据。据我所知,这个客户本月没有解除分配。

麻烦部分是:

和(trunc(d.deallocation_date)to_date(:run_date)和last_day(:run_date)或f.deallocation_date之间为null))

因为无论ip_address_usages表中的内容是什么,它都应该将IP过滤为29,但是计数保持在57,这意味着它全部选择它们。

set pagesize 2000
set linesize 300
break on report on customer_name skip 1
compute sum label Total of GigaBytes_Sent GigaBytes_Received IPS_IN_USE on customer_name
compute sum label Grand-Total of GigaBytes_Sent GigaBytes_Received IPS_IN_USE on REPORT
column GigaBytes_Sent format 999,999,999,999.99
column GigaBytes_Received format 999,999,999,999.99

select customer_name,
       substr(decode(vcd_managed,'Y',vm_name,'N',vm_group_name || ' ' || vm_display_name),1,100) vm_name,
       decode(vcd_managed,'Y',null,'N',vm_display_name) vm_display_name,
       sum(bytes_sent)*1.8/power(10,9) GigaBytes_Sent,
       sum(bytes_received)*1.8/power(10,9) GigaBytes_Received,
       count(unique e.ip_address_id) IPS_IN_USE
  from customers a,
       vm_groups b, 
       vms c, 
       vm_ip_address_histories d, 
       ip_address_usages e
 where a.customer_id = b.customer_id
   and b.vm_group_id=c.vm_group_id
   and c.vm_id=d.vm_id
   and d.ip_address_id=e.ip_address_id
   and trunc(e.datetime) between :run_date and last_day(:run_date)
   and exists (select f.deallocation_date 
                   from vm_ip_address_histories f 
                   where f.vm_id = d.vm_id 
                   and (trunc(d.deallocation_date) between to_date(:run_date) and last_day(:run_date) or f.deallocation_date is null))
   and inactive = 'N'
   and a.customer_id = 30
--   and (bytes_sent > 0 or bytes_received > 0)
 group by customer_name,
       substr(decode(vcd_managed,'Y',vm_name,'N',vm_group_name || ' ' || vm_display_name),1,100),
       decode(vcd_managed,'Y',null,'N',vm_display_name)
 order by 1,2,3
/

我试图总结从ip_address_usages表发送和接收的字节, 同时计算属于客户之间的不同ip_address_id 该月的第一天和最后一天的释放日期为null, 或者介于该月的第一天和最后一天之间的值。 如果我在下面运行第一个查询,它将返回与客户关联的错误数量的IP地址。

我显然可以看到它没有计算当月的最后一天和第一天, 但是,当我添加它时,它会抛出摘要,如下所示。 我试图这样做,所以摘要和IP帐户是正确的。

以下是表格关系,我只包括相关的描述。

    Customers > VM_Groups  
    VM_Groups > VMS 
    VMS > VM_IP_ADDRESS_HISTORIES 
    VM_IP_ADDRESS_HISTORIES > IP_ADDRESSES by ip_address_id, 
    IP_ADDRESSES > IP_ADDRESS_USAGES "this is where bytes sent and received is" relates to IP_ADDRESSES by ip_address_id

为了安全问题,我屏蔽了信息,但您不需要它来回答这个问题:

从第一个查询返回的值是错误的,计数是57而不是29:

    variable run_date varchar2(30)
    exec :run_date := to_date('1-oct-14')

    set pagesize 2000
    set linesize 300
    break on report on customer_name skip 1
    compute sum label Total of GigaBytes_Sent GigaBytes_Received IPS_IN_USE on customer_name
    compute sum label Grand-Total of GigaBytes_Sent GigaBytes_Received IPS_IN_USE on REPORT
    column GigaBytes_Sent format 999,999,999,999.99
    column GigaBytes_Received format 999,999,999,999.99

    select customer_name,
           substr(decode(vcd_managed,'Y',vm_name,'N',vm_group_name || ' ' || vm_display_name),1,100) vm_name,
           decode(vcd_managed,'Y',null,'N',vm_display_name) vm_display_name,
           sum(bytes_sent)*1.8/power(10,9) GigaBytes_Sent,
           sum(bytes_received)*1.8/power(10,9) GigaBytes_Received,
           count(unique e.ip_address_id) IPS_IN_USE
      from customers a,
           vm_groups b, 
           vms c, 
           vm_ip_address_histories d, 
           ip_address_usages e
     where a.customer_id = b.customer_id
       and b.vm_group_id=c.vm_group_id
       and c.vm_id=d.vm_id
       and d.ip_address_id=e.ip_address_id
       and trunc(e.datetime) between :run_date and last_day(:run_date)
       and inactive = 'N'
       and a.customer_id = 30
    --   and (bytes_sent > 0 or bytes_received > 0)
     group by customer_name,
           substr(decode(vcd_managed,'Y',vm_name,'N',vm_group_name || ' ' || vm_display_name),1,100),
           decode(vcd_managed,'Y',null,'N',vm_display_name)
     order by 1,2,3
    /


    CUSTOMER_NAME              VM_NAME                                                  VM_DISPLAY_NAME         GIGABYTES_SENT  GIGABYTES_RECEIVED IPS_IN_USE
    ------------------------------ ---------------------------------------------------------------------------------------------------- ------------------------------ ------------------- ------------------- ----------
    mask/masked        mask/masked                                                                                  198.59                    168.57            29
                       mask/masked                                                                                  43.35                      33.95            19
                       mask/masked                                                                                  164.04                    135.86             9
    ***************************************************************************************************************************************************************************************************     
    Total                                                                                       405.98                    338.38            57

    set pagesize 2000
    set linesize 300
    break on report on customer_name skip 1
    compute sum label Total of GigaBytes_Sent GigaBytes_Received IPS_IN_USE on customer_name
    compute sum label Grand-Total of GigaBytes_Sent GigaBytes_Received IPS_IN_USE on REPORT
    column GigaBytes_Sent format 999,999,999,999.99
    column GigaBytes_Received format 999,999,999,999.99

    select customer_name,
           substr(decode(vcd_managed,'Y',vm_name,'N',vm_group_name || ' ' || vm_display_name),1,100) vm_name,
           decode(vcd_managed,'Y',null,'N',vm_display_name) vm_display_name,
           sum(bytes_sent)*1.8/power(10,9) GigaBytes_Sent,
           sum(bytes_received)*1.8/power(10,9) GigaBytes_Received,
           count(unique e.ip_address_id) IPS_IN_USE
      from customers a,
           vm_groups b, 
           vms c, 
           vm_ip_address_histories d, 
           ip_address_usages e
     where a.customer_id = b.customer_id
       and b.vm_group_id=c.vm_group_id
       and c.vm_id=d.vm_id
       and d.ip_address_id=e.ip_address_id
       and trunc(e.datetime) between :run_date and last_day(:run_date)
       and (d.deallocation_date is null or d.deallocation_date between to_date(:run_date) and last_day(:run_date))
       and inactive = 'N'
       and a.customer_id =30
    --   and (bytes_sent > 0 or bytes_received > 0)
     group by customer_name,
           substr(decode(vcd_managed,'Y',vm_name,'N',vm_group_name || ' ' || vm_display_name),1,100),
           decode(vcd_managed,'Y',null,'N',vm_display_name)
     order by 1,2,3
    /

    CUSTOMER_NAME              VM_NAME                                                  VM_DISPLAY_NAME         GIGABYTES_SENT  GIGABYTES_RECEIVED IPS_IN_USE
    ------------------------------ ---------------------------------------------------------------------------------------------------- ------------------------------ ------------------- ------------------- ----------
    mask/masked        mask/masked                                                                                  .00                          .01              8
                       mask/masked                                                                                  43.35                      33.95             18
                       mask/masked                                                                                  .00                          .01              3
    ***************************************************************************************************************************************************************************************************                                                                 
    Total                                                                                       43.35                        33.97          29

    select max(deallocation_date) 
    from vm_ip_address_histories a, 
    vms b, vm_groups c, 
    customers d 
    where a.vm_id = b.vm_id 
    and b.vm_group_id = c.vm_group_id 
    and c.customer_id = d.customer_id 
    and d.customer_id = 30
    /

    MAX(DEALLOCATION_DATE)
    ---------------------------------------------------------------------------
    04-AUG-14 06.04.30.000000 PM


    select distinct e.ip_address, 
    a.customer_name,
    c.vm_id, 
    d.allocation_date, 
    d.deallocation_date
    from customers a, 
    vm_groups b, 
    vms c, 
    vm_ip_address_histories d, 
    ip_addresses e 
    where a.customer_id=30
    and a.customer_id = b.customer_id
    and b.vm_group_id = c.vm_group_id
    and c.vm_id = d.vm_id
    and d.ip_address_id = e.ip_address_id
    and exists (select * from vm_ip_address_histories where d.deallocation_date is null or trunc(d.deallocation_date) >= to_date('1-oct-14') )
    /

      2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17  
    IP_ADDRESS           CUSTOMER_NAME               VM_ID ALLOCATION_DATE                                 DEALLOCATION_DATE
    -------------------------------- ------------------------------ ---------- --------------------------------------------------------------------------- ---------------------------------------------------------------------------
    XXXXXXXX             XXXXXXXXX               27374 17-JUN-14 03.58.48.000000 PM
    XXXXXXXX             XXXXXXXXX               27374 30-JUL-14 03.18.41.000000 PM
    XXXXXXXX             XXXXXXXXX               27374 17-JUN-14 04.43.48.000000 PM
    XXXXXXXX             XXXXXXXXX               27374 17-JUN-14 03.43.48.000000 PM
    XXXXXXXX             XXXXXXXXX                 365 17-JAN-14 03.02.25.000000 PM
    XXXXXXXX             XXXXXXXXX               27374 17-JUN-14 03.43.48.000000 PM
    XXXXXXXX             XXXXXXXXX                1586 26-FEB-14 10.48.18.000000 AM
    XXXXXXXX             XXXXXXXXX                 365 17-JAN-14 03.02.25.000000 PM
    XXXXXXXX             XXXXXXXXX               27374 28-JUN-14 12.45.22.000000 PM
    XXXXXXXX             XXXXXXXXX               27374 21-JUN-14 01.29.23.000000 PM
    XXXXXXXX             XXXXXXXXX               27374 17-JUN-14 04.58.48.000000 PM

    IP_ADDRESS           CUSTOMER_NAME               VM_ID ALLOCATION_DATE                                 DEALLOCATION_DATE
    -------------------------------- ------------------------------ ---------- --------------------------------------------------------------------------- ---------------------------------------------------------------------------
    XXXXXXXX             XXXXXXXXX                 365 17-JAN-14 03.02.25.000000 PM
    XXXXXXXX             XXXXXXXXX               27374 17-JUN-14 03.58.48.000000 PM
    XXXXXXXX             XXXXXXXXX               27374 17-JUN-14 03.43.48.000000 PM
    XXXXXXXX             XXXXXXXXX                 365 17-JAN-14 03.02.25.000000 PM
    XXXXXXXX             XXXXXXXXX                 365 20-FEB-14 04.47.33.000000 PM
    XXXXXXXX             XXXXXXXXX               27374 17-JUN-14 04.13.48.000000 PM
    XXXXXXXX             XXXXXXXXX               27374 17-JUN-14 03.58.48.000000 PM
    XXXXXXXX             XXXXXXXXX               27374 17-JUN-14 04.43.48.000000 PM
    XXXXXXXX             XXXXXXXXX                1586 17-JUN-14 02.13.47.000000 PM
    XXXXXXXX             XXXXXXXXX               27374 04-AUG-14 06.04.30.000000 PM
    XXXXXXXX             XXXXXXXXX                1586 25-FEB-14 05.03.12.000000 PM

    IP_ADDRESS           CUSTOMER_NAME               VM_ID ALLOCATION_DATE                                 DEALLOCATION_DATE
    -------------------------------- ------------------------------ ---------- ---------------------------select customer_name,
       substr(decode(vcd_managed,'Y',vm_name,'N',vm_group_name || ' ' || vm_display_name),1,100) vm_name,
       decode(vcd_managed,'Y',null,'N',vm_display_name) vm_display_name,
       sum(bytes_sent)*1.8/power(10,9) GigaBytes_Sent,
       sum(bytes_received)*1.8/power(10,9) GigaBytes_Received,
       count(unique e.ip_address_id) IPS_IN_USE
  from customers a,
       vm_groups b, 
       vms c, 
       vm_ip_address_histories d, 
       ip_address_usages e
 where a.customer_id = b.customer_id
   and b.vm_group_id=c.vm_group_id
   and c.vm_id=d.vm_id
   and d.ip_address_id=e.ip_address_id
   and trunc(e.datetime) between :run_date and last_day(:run_date)
   and exists (select * from vm_ip_address_histories f where deallocation_date is null or trunc(deallocation_date) between :run_date and last_day(:run_date) )
   and inactive = 'N'
   and a.customer_id = 30
--   and (bytes_sent > 0 or bytes_received > 0)
 group by customer_name,
       substr(decode(vcd_managed,'Y',vm_name,'N',vm_group_name || ' ' || vm_display_name),1,100),
       decode(vcd_managed,'Y',null,'N',vm_display_name)
 order by 1,2,3
------------------------------------------------ ---------------------------------------------------------------------------
    XXXXXXXX             XXXXXXXXX                 365 17-JAN-14 03.02.25.000000 PM
    XXXXXXXX             XXXXXXXXX                 365 17-JAN-14 03.02.25.000000 PM
    XXXXXXXX             XXXXXXXXX                 365 17-JAN-14 03.02.25.000000 PM
    XXXXXXXX             XXXXXXXXX               27374 17-JUN-14 04.13.48.000000 PM
    XXXXXXXX             XXXXXXXXX               27374 17-JUN-14 03.43.48.000000 PM
    XXXXXXXX             XXXXXXXXX               27374 28-JUN-14 12.30.23.000000 PM
    XXXXXXXX             XXXXXXXXX               27374 17-JUN-14 04.43.48.000000 PM

    29 rows selected.




    select distinct e.ip_address
    from customers a, 
    vm_groups b, 
    vms c, 
    vm_ip_address_histories d, 
    ip_addresses e 
    where a.customer_id=30
    and a.customer_id = b.customer_id
    and b.vm_group_id = c.vm_group_id
    and c.vm_id = d.vm_id
    and d.ip_address_id = e.ip_address_id
    and (d.deallocation_date is null or d.deallocation_date between to_date('01-10-2014', 'DD-MM-YYYY') and to_date('31-10-2014 23:59:59', 'DD-MM-YYYY HH24:MI:SS'))
    /  

    IP_ADDRESS
    --------------------------------
    MASKED FOR SECURITY

    29 rows selected.



    select count(distinct e.ip_address)
    from customers a, 
    vm_groups b, 
    vms c, 
    vm_ip_address_histories d, 
    ip_addresses e 
    where a.customer_id=30
    and a.customer_id = b.customer_id
    and b.vm_group_id = c.vm_group_id
    and c.vm_id = d.vm_id
    and d.ip_address_id = e.ip_address_id
    and (d.deallocation_date is null or d.deallocation_date between to_date('01-10-2014', 'DD-MM-YYYY') and to_date('31-10-2014 23:59:59', 'DD-MM-YYYY HH24:MI:SS'))
    /

    COUNT(DISTINCTE.IP_ADDRESS)
    ---------------------------
                 29

所以我使用相关子查询编写了另一个查询来尝试仅过滤掉在该范围内分配和解除分配的ip,但它仍然返回57但是正确的使用数据。现在显然只有29个,因为我已经完全展示了以上。因此,它在我的查询中的东西。请查看并告诉我查询有什么问题。

    select customer_name,
           substr(decode(vcd_managed,'Y',vm_name,'N',vm_group_name || ' ' || vm_display_name),1,100) vm_name,
           decode(vcd_managed,'Y',null,'N',vm_display_name) vm_display_name,
           sum(bytes_sent)*1.8/power(10,9) GigaBytes_Sent,
           sum(bytes_received)*1.8/power(10,9) GigaBytes_Received,
           count(unique e.ip_address_id) IPS_IN_USE
      from customers a,
           vm_groups b, 
           vms c, 
           vm_ip_address_histories d, 
           ip_address_usages e
     where a.customer_id = b.customer_id
       and b.vm_group_id=c.vm_group_id
       and c.vm_id=d.vm_id
       and d.ip_address_id=e.ip_address_id
       and trunc(e.datetime) between :run_date and last_day(:run_date)
       and exists (select * from vm_ip_address_histories f where deallocation_date is null or trunc(deallocation_date) between :run_date and last_day(:run_date) )
       and inactive = 'N'
       and a.customer_id = 30
    --   and (bytes_sent > 0 or bytes_received > 0)
     group by customer_name,
           substr(decode(vcd_managed,'Y',vm_name,'N',vm_group_name || ' ' || vm_display_name),1,100),
           decode(vcd_managed,'Y',null,'N',vm_display_name)
     order by 1,2,3

基本上使用此查询我希望它仅在相关子查询的范围内存在时进行汇总和计数

同样的事情

select customer_name,
       substr(decode(vcd_managed,'Y',vm_name,'N',vm_group_name || ' ' || vm_display_name),1,100) vm_name,
       decode(vcd_managed,'Y',null,'N',vm_display_name) vm_display_name,
       sum(bytes_sent)*1.8/power(10,9) GigaBytes_Sent,
       sum(bytes_received)*1.8/power(10,9) GigaBytes_Received,
       count(unique e.ip_address_id) IPS_IN_USE
  from customers a,
       vm_groups b, 
       vms c, 
       vm_ip_address_histories d, 
       ip_address_usages e
 where a.customer_id = b.customer_id
   and b.vm_group_id=c.vm_group_id
   and c.vm_id=d.vm_id
   and d.ip_address_id=e.ip_address_id
   and trunc(e.datetime) between :run_date and last_day(:run_date)
   and exists (select f.deallocation_date from vm_ip_address_histories f where f.vm_id = d.vm_id and (f.deallocation_date is null or trunc(f.deallocation_date) between :run_date and last_day(:run_date)) )
   and inactive = 'N'
   and a.customer_id = 30
--   and (bytes_sent > 0 or bytes_received > 0)
 group by customer_name,
       substr(decode(vcd_managed,'Y',vm_name,'N',vm_group_name || ' ' || vm_display_name),1,100),
       decode(vcd_managed,'Y',null,'N',vm_display_name)
 order by 1,2,3

2 个答案:

答案 0 :(得分:0)

LAST_DAY函数返回作为输入提供的月份的最后一天的日期,但它还包括您提供的日期的时间组件,因此您的子句

    d.deallocation_date between to_date(:run_date) and last_day(:run_date))

应该是

   truncate(d.deallocation_date) between to_date(:run_date) and last_day(:run_date))

您的代码设置:run_date为没有时间组件的varchar字段,因此last_day(:run_date)将在00:00:00,因此如果d.deallocation_date的时间晚于时间,则它会赢得'被选中。

SQL> variable run_date varchar2(30)
SQL> exec :run_date := to_date('1-oct-14')

SQL>  select to_char(to_date(:run_date), 'yyyy-mm-dd hh24:mi:ss') as first_of_month,
2*     to_char(last_day(to_date(:run_date)), 'yyyy-mm-dd hh24:mi:ss') as last_of_month from dual;

FIRST_OF_MONTH      LAST_OF_MONTH
------------------- -------------------
2014-10-01 00:00:00 2014-10-31 00:00:00

答案 1 :(得分:0)

关于这部分:

(trunc(d.deallocation_date) between to_date(:run_date) and last_day(:run_date) 
or f.deallocation_date is null))

您是否应在deallocation_date两侧的同一张桌子中使用or