Вот более прямая часть вопроса. Что-то не так со следующим запросом. Он возвращает каждый ip_address, когда-либо использовавшийся клиентом, вместо того, чтобы фильтровать его за текущий месяц. Когда Deallocation_date имеет значение null или между датами, это единственные IP-адреса, которые необходимо выбрать. Запрос, приведенный ниже, является моей попыткой сделать это с помощью коррелированного подзапроса, используя, если он существует в этих условиях, подсчет и сумму для этих IP-адресов. Однако ниже я показываю, что существует только 29 IP-адресов с datelocation_date = null, которые были освобождены между этими датами, потому что для этого клиента максимальная дата освобождения приходится на август. Я знаю, что он выбирает все IP-адреса, когда-либо назначенные клиенту. Пожалуйста, помогите мне исправить подзапрос, чтобы вернуть правильные данные. Я просто не настолько хорошо разбираюсь в SQL, чтобы понять, в чем моя ошибка. Я знаю, что это как-то связано с тем, как я использую or.
Я также знаю, как было указано, что он будет выбирать только до 00:00:00 в последний день месяца, и пока я согласен с этим, я могу исправить это позже. Мне нужно, чтобы он возвращал правильные данные. Насколько я знаю, для этого клиента в этом месяце не было ни одного освобождения.
Проблемная часть:
И (trunc(d.deallocation_date) между to_date(:run_date) и last_day(:run_date) или f.deallocation_date равно null))
Потому что это должно отфильтровать IP-адреса до 29, независимо от того, что находится в таблице ip_address_usages, но счетчик остается на уровне 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, принадлежащие клиенту между первым и последним днем месяца, дата освобождения которых равна нулю, или значение, которое находится между первым и последний день месяца. Когда я запускаю первый запрос ниже, он возвращает неправильное количество 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 ответа
Функция 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
Что касается этой части:
(trunc(d.deallocation_date) between to_date(:run_date) and last_day(:run_date)
or f.deallocation_date is null))
Должны ли вы использовать deallocation_date
из одной и той же таблицы с обеих сторон or
?
Похожие вопросы
Новые вопросы
sql
Язык структурированных запросов (SQL) - это язык запросов к базам данных. Вопросы должны включать примеры кода, структуру таблицы, примеры данных и тег для используемой реализации СУБД (например, MySQL, PostgreSQL, Oracle, MS SQL Server, IBM DB2 и т. Д.). Если ваш вопрос относится исключительно к конкретной СУБД (использует определенные расширения / функции), используйте вместо этого тег этой СУБД. Ответы на вопросы, помеченные SQL, должны использовать стандарт ISO / IEC SQL.