Я пытаюсь создать запрос, который будет выполнять следующее:
1) Запросить строку с заданным "acctuniqueid", которая имеет второе по величине значение для "acctoutputoctets", или если найденная совпадающая строка не найдена, верните 0
2) Выполните следующий расчет 250 + 350- (возвращаемое значение "acctinputoctets" + возвращаемое значение "acctoutputoctets" || "0")
Использование "a25d16693309cdb4807effe00a9f076c" в качестве поля "acctuniqueid".
Название таблицы: radacct
+-----------+----------------------------------+-----------------+------------------+
| radacctid | acctuniqueid | acctinputoctets | acctoutputoctets |
+-----------+----------------------------------+-----------------+------------------+
| 5 | a25d16693309cdb4807effe00a9f076c | 150 | 250 |
| 8 | a25d16693309cdb4807effe00a9f076c | 250 | 350 |
+-----------+----------------------------------+-----------------+------------------+
+-----------+----------------------------------+-----------------+------------------+
| radacctid | acctuniqueid | acctinputoctets | acctoutputoctets |
+-----------+----------------------------------+-----------------+------------------+
| 4 | a25d16693309cdb4807effe00a9f076c | 250 | 350 |
+-----------+----------------------------------+-----------------+------------------+
В примере №1: 250 + 350- (150 + 250) = 200 Таким образом, ожидаемый результат равен 200
В примере №2: 250 + 350- (0) = 600. Таким образом, ожидаемый результат - 600
Query, с которым я уже занимался:
SELECT (SUM(250)+SUM(350)-((SUM(IFNULL(acctinputoctets,0)))+
(SUM(IFNULL(acctoutputoctets,0))))
)
FROM
( SELECT *,IFNULL(acctinputoctets,0),
IFNULL(acctoutputoctets,0)
FROM radacct
WHERE acctuniqueid = 'a25d16693309cdb4807effe00a9f076c'
ORDER BY acctoutputoctets DESC
LIMIT 1 , 1
) as meh
Что возвращает что-то для примера # 1, но для примера # 2 я получаю NULL в качестве результата.
Следует отметить, что в вышеприведенном запросе "250", "350" и "a25d16693309cdb4807effe00a9f076c" были добавлены вручную для тестирования и удобства чтения, но позже будут заменены выводом переменной времени выполнения.
Я пробовал различные итерации, комбинации и места размещения IFNULL и COALESCE и попытался найти похожие сообщения о проблемах/решениях в Интернете, но не смог найти что-либо достаточно близко к тому, что я делаю, что у меня есть " Ага!" момент еще.
Учитывая мой (недостаток) опыта SQL, я предполагаю, что либо (а) это что-то действительно простое, что кто-то сразу обнаружит, и/или (б) я поступил с моим запросом совершенно неправильно, и есть другое и более правильный способ структурирования этого запроса, который находится за пределами моего текущего уровня знаний.
В 4 утра этим утром, и после нескольких часов ругательства, мольбы и торг - я, наконец, признал поражение, и поэтому любая помощь была бы высоко оценена.
Заранее спасибо.
Кажется, это работает для меня:
Пример №1
CREATE TABLE radacct (
radacctid int,
acctuniqueid nvarchar(50),
acctinputoctets int,
acctoutputoctets int
);
INSERT INTO radacct values
(5, 'a25d16693309cdb4807effe00a9f076c', 150, 250),
(8, 'a25d16693309cdb4807effe00a9f076c', 250, 350)
SELECT 250 + 350
- COALESCE((SELECT acctinputoctets FROM radacct ORDER BY acctoutputoctets DESC LIMIT 1, 1), 0)
- COALESCE((SELECT acctoutputoctets FROM radacct ORDER BY acctoutputoctets DESC LIMIT 1, 1), 0)
Пример №2
CREATE TABLE radacct (
radacctid int,
acctuniqueid nvarchar(50),
acctinputoctets int,
acctoutputoctets int
);
INSERT INTO radacct values
(4, 'a25d16693309cdb4807effe00a9f076c', 250, 350);
SELECT 250 + 350
- COALESCE((SELECT acctinputoctets FROM radacct ORDER BY acctoutputoctets LIMIT 1, 1), 0)
- COALESCE((SELECT acctoutputoctets FROM radacct ORDER BY acctoutputoctets LIMIT 1, 1), 0)
Однако, если есть несколько строк, связанных для того, чтобы иметь второе наибольшее значение в acctoutputoctects, тогда результат будет довольно случайным. Например, если в примере # 1 обе строки имели значение 350 в столбце acctoutputoctects, тогда результат будет зависеть от того, как значения были вставлены, поскольку обе строки соответствуют критериям, но имеют разные значения в столбце acctinputoctects (что влияет на ответ). Если вы дадите более подробную информацию о том, как вы хотите, чтобы связь была нарушена, я был бы рад изменить код для его размещения.
Важнейшей проблемой здесь является решение в случае ничьих, которые acctinputoctets выбрать. Этот неприятный код пытается выбрать самые последние самые высокие и самые высокие значения на основе radacctid перед левым присоединением, чтобы получить окончательный результат
drop table if exists t;
create table t( radacctid int, acctuniqueid varchar(40), acctinputoctets int, acctoutputoctets int);
insert into t values
( 5 , 'a25d16693309cdb4807effe00a9f076c' , 150 , 250),
( 8 , 'a25d16693309cdb4807effe00a9f076c' , 250 , 350),
( 9 , 'a25d16693309cdb4807effe00a9f076c' , 200 , 250),
( 4 , 'b25d16693309cdb4807effe00a9f076c' , 10 , 10),
( 6 , 'b25d16693309cdb4807effe00a9f076c' , 250 , 350),
( 7 , 'c25d16693309cdb4807effe00a9f076c' , 20 , 30);
select mm.acctuniqueid,mm.maxid,mm.maxin,mm.maxout ,
sm.acctuniqueid,sm.secondmaxid,sm.secondmaxin,sm.secondmaxout,
(ifnull(mm.maxin,0) + ifnull(mm.maxout,0)) -
(ifnull(sm.secondmaxin,0) + ifnull(sm.secondmaxout,0)) as Total
from
(
select t.acctuniqueid,t.radacctid maxid,t.acctinputoctets maxin,t.acctoutputoctets maxout
from t
join
(
select t.acctuniqueid,s.maxout, max(radacctid) maxid #adjust maxid as required
from
(
select acctuniqueid, max(acctoutputoctets) maxout
from t
where acctoutputoctets = (select max(acctoutputoctets) from t t1 where t1.acctuniqueid = t.acctuniqueid)
group by acctuniqueid
) s
join t on t.acctuniqueid = s.acctuniqueid and t.acctoutputoctets = s.maxout
group by t.acctuniqueid,s.maxout
) s
on s.acctuniqueid = t.acctuniqueid and s.maxid = t.radacctid
) mm
left join
(
select t.acctuniqueid,t.radacctid secondmaxid,t.acctinputoctets secondmaxin,t.acctoutputoctets secondmaxout
from t
join
(
select t.acctuniqueid,s.secondmaxout, max(radacctid) secondmaxid #adjust secondmaxid as required
from
(
select acctuniqueid, max(acctoutputoctets) secondmaxout
from t
where acctoutputoctets < (select max(acctoutputoctets) from t t1 where t1.acctuniqueid = t.acctuniqueid)
group by acctuniqueid
) s
join t on t.acctuniqueid = s.acctuniqueid and t.acctoutputoctets = secondmaxout
group by t.acctuniqueid,s.secondmaxout
) s
on s.acctuniqueid = t.acctuniqueid and s.secondmaxid = t.radacctid
) sm
on mm.acctuniqueid = sm.acctuniqueid
+----------------------------------+-------+-------+--------+----------------------------------+-------------+-------------+--------------+-------+
| acctuniqueid | maxid | maxin | maxout | acctuniqueid | secondmaxid | secondmaxin | secondmaxout | Total |
+----------------------------------+-------+-------+--------+----------------------------------+-------------+-------------+--------------+-------+
| a25d16693309cdb4807effe00a9f076c | 8 | 250 | 350 | a25d16693309cdb4807effe00a9f076c | 9 | 200 | 250 | 150 |
| b25d16693309cdb4807effe00a9f076c | 6 | 250 | 350 | b25d16693309cdb4807effe00a9f076c | 4 | 10 | 10 | 580 |
| c25d16693309cdb4807effe00a9f076c | 7 | 20 | 30 | NULL | NULL | NULL | NULL | 50 |
+----------------------------------+-------+-------+--------+----------------------------------+-------------+-------------+--------------+-------+
3 rows in set (0.01 sec)
Возможно, это может быть упрощено, если вам просто понадобилось максимальное (или мин) значение, чтобы перейти с максимальным значением в случае ничьей.