Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2008.04.20;
Скачать: CL | DM;

Вниз

Расчет среднего значения.   Найти похожие ветки 

 
Neket   (2007-11-17 13:17) [0]

Как расчитать среднее только по первым двум значениям? Т.е. Имеется к примеру такая табличка:

Name   |   Value | Date
Name1 |   15      | 15.07.2006
Name1 |   14      | 20.07.2006
Name1 |   11      | 12.07.2006
Name1 |   7        | 11.07.2006
Name2 |   45      |  01.07.2006
Name2 |   37      |  06.07.2006
Name2 |   25      |  16.07.2006
Name2 |   18      |  26.07.2006
..... ну и так далее


И как теперь вычислить среднее значение AVG только первых двух значений. Т.е. чтобы была к примеру такая табличка

Name   |   Value_AVG
Name1 |        14.5
Name2 |        41
..... ну и так далее


P.S. Подозреваю что необходимо использовать аналитический функции, но к сожалению я с ними очень не знаком поэто му решил к вам обратиться. Кто может подскажите пожалуйста :-)


 
Kolan ©   (2007-11-17 13:30) [1]

Нужно сгрупировать.

Table:
Name   |   Value | Date
Name1 |   15      | 15.07.2006
Name1 |   14      | 20.07.2006
Name1 |   11      | 12.07.2006
Name1 |   7        | 11.07.2006
Name2 |   45      |  01.07.2006
Name2 |   37      |  06.07.2006
Name2 |   25      |  16.07.2006
Name2 |   18      |  26.07.2006


SELECT Name, AVG(Value) AS Value_AVG
FROM Table
Group BY Name


 
Neket   (2007-11-17 13:35) [2]

Да но в это случае расчет среднего будет произодиться по всем четырем начениям, а задача стоит в том чтобы расчитать только по первым двум значениям. Т.е. NAME1 только за 15.07.2006 и 20.07.2006, NAME2 только за 11.07.2006 и 01.07.2006


 
Kolan ©   (2007-11-17 14:09) [3]

> по первым двум значениям

Ну сделайте нужный SELECT.

SELECT * FROM Table
WHERE (Date = "2006-07-15") OR (&#133)


А уже этот SELECT — см. [1]


 
sniknik ©   (2007-11-17 14:12) [4]

> а задача стоит в том чтобы расчитать только по первым двум значениям.
значит подбери условие которое отбирает только первые два... (по какому признаку первые?... порядковые номера так эфемерны, и обманчивы...)

> Т.е. NAME1 только за 15.07.2006 и 20.07.2006, NAME2 только за 11.07.2006 и 01.07.2006
ну вот как вариант и пиши это в условии отбора, только в SQL -
WHERE Name="Name1" AND Date=... и тд....


 
Neket   (2007-11-17 14:21) [5]

Дело в том что даты могут быть разными а слолбец value отсортирован по убыванию. И задача посчитать среднее первых двух максимальных значений.
Т.е. Даты могуть быть абсолютоно разными... Это я писал для примера...
У меня есть селект который выбирает максимальные значения VALUE за месяц по недельно. И необходимо вычислить среднее значния дву максимальных значений value за четыре недели. Витеевато наверное объяснил. Извините. :-)


 
Kolan ©   (2007-11-17 14:50) [6]

> И необходимо вычислить среднее значния дву максимальных
> значений value за четыре недели.

Вот и савтено условие.

Какая СУБД? SQL Server 2005 съест SELECT TOP N(кажется)&#133


 
Neket   (2007-11-17 14:55) [7]

Oracle.... SELECT TOP N не прокатит


 
Neket   (2007-11-17 15:22) [8]

Можно даже не много перфразировать задачу...
Как имея такую таблицу:
tabel1
Name   |   Value | Date
Name1 |   15      | 15.07.2006
Name1 |   14      | 20.07.2006
Name1 |   11      | 12.07.2006
Name1 |   7        | 11.07.2006
Name2 |   45      |  01.07.2006
Name2 |   37      |  06.07.2006
Name2 |   25      |  16.07.2006
Name2 |   18      |  26.07.2006
..... ну и так далее
получить такую
Table2
Name   |   Value | Date
Name1 |   15      | 15.07.2006
Name1 |   14      | 20.07.2006
Name2 |   45      |  01.07.2006
Name2 |   37      |  06.07.2006
..... ну и так далее

Т.е. Чтобы выводились только первые два значения каждого name из table1


 
Kolan ©   (2007-11-17 15:46) [9]

Если я правильно понимаю задачу, то тебе надо научится выбирать две верхние строки в отсортированном наборо данных. Как сделать это в ORACLE я незнаю. Но точно уверен, что это можно сделать написав соотв хрон процедуру. Кажется в ORACLE язык называется PL SQL. Но(!) в правильности такого решения я не уверен&#133


 
Neket   (2007-11-17 16:03) [10]

Да все верно... В оракле самый простой способ это написать процедуру, но задача состоит имено в том чтобы вычислить значения при помощи обычного select-а.


 
Kolan ©   (2007-11-17 16:06) [11]

Может так:


SELECT * FROM Table
WHERE
    (Value = (SELECT Max(Value) FROM Table))
 OR (Value = (
      SELECT Max(Value) FROM Table WHERE Value <> (SELECT Max(Value) FROM Table)))


Это идея&#133


 
Kolan ©   (2007-11-17 16:11) [12]

Иными словами:

DECLARE @MaxValue int;
DECLARE @SecondFromMax int;

SET @MaxValue = SELECT Max(Value) FROM Table;
SET @SecondFromMax = SELECT Max(Value) FROM Table WHERE Value <> @MaxValue;

SELECT * FROM Table
WHERE (Value = @MaxValue) OR (Value = @SecondFromMax)


 
Neket   (2007-11-17 16:41) [13]

Спасибо... Но уже сам догадался... :-) Теперь другой вопрос... :-( Так сложилось что колличество значений не стаическое а динамическое. Т.е. Не фиксировано 4 значения каждого Name, а колеблится от 1 до 4. В связи с этим необходимо если колличество значений name<>N, тогда не обрабатывать эти строки...
иными словами в селект
SELECT * FROM Table
WHERE
   (Value = (SELECT Max(Value) FROM Table))
OR (Value = (
     SELECT Max(Value) FROM Table WHERE Value <> (SELECT Max(Value) FROM Table)))
необходимо добавить условие не обрабатывать name-ы если их колличество не равно N, где N - может быть равно от 2 до 4.


 
Kolan ©   (2007-11-17 16:48) [14]


> Т.е. Не фиксировано 4 значения каждого Name, а колеблится
> от 1 до 4. В связи с этим необходимо если колличество значений
> name<>N, тогда не обрабатывать эти строки&#133

Это не понял&#133


> необходимо добавить условие не обрабатывать name-ы если
> их колличество не равно N, где N &#151; может быть равно от 2
> до 4.

А тут что трудно?
SELECT Name
FROM Tabel
WHERE Count(*) BETWEEN 2 AND 4


Или я не понял вопрос&#133
GROUP BY Name


 
Anatoly Podgoretsky ©   (2007-11-17 17:01) [15]

Надо тор 2 использовать во внутреннем селекта, а по нему уже брать среднее.


 
Neket   (2007-11-17 17:12) [16]

А есть какая нибудь функция в SQL  которой задаеш имя столбца, значение какое либо из этого столбца а она возвращает сколько раз встречается это значение. Т.е.
tabel1
Name   |   Value | Date
Name1 |   15      | 15.07.2006
Name1 |   14      | 20.07.2006
Name2 |   45      |  01.07.2006
Name2 |   37      |  06.07.2006
Name2 |   25      |  16.07.2006

Count_Zna4(Tabel1,"NAME1") =2
Count_Zna4(Tabel1,"NAME2") =3
ну или чегонибудь похожее...


 
Anatoly Podgoretsky ©   (2007-11-17 18:00) [17]

> Neket  (17.11.2007 17:12:16)  [16]

Есть, это count


 
Johnmen ©   (2007-11-17 22:14) [18]

Написание ХП обеспечит максимум прозрачности, скорости и функциональной гибкости. В данном случае.


 
sdts   (2007-11-17 22:19) [19]


> Johnmen ©   (17.11.07 22:14) [18]
> Написание ХП обеспечит максимум прозрачности, скорости и
> функциональной гибкости. В данном случае.

эта, а есть противоположные случаи?


 
Johnmen ©   (2007-11-17 22:27) [20]


> эта, а есть противоположные случаи?

Для простых выборок разве что.


 
Petr V. Abramov ©   (2007-11-17 22:34) [21]

> Подозреваю что необходимо использовать аналитический функции
100% правильно понимаешь.
понимаю, их много, но сейчас за тебя смотреть лень, а навскидку не помню


 
Neket   (2007-11-18 09:57) [22]

В первом случае как раз воспользовался аналитической функцией совместно с max().
select
name,
max(value_avg)
from
(select
name,
avg(value)  OVER (ORDER BY value rows BETWEEN 1  PRECEDING AND CURRENT ROW) as value_avg
from
tabel1
group by name) name_AVG
group by name

Как-то так :-)
Но вот теперь стал вопрос как подвизать сюда этот count или похожую функцию которая позволит не рассматривать в TABLE значения name если его колличесто меньше N где N можно задавать произвольно.


 
Кщд ©   (2007-11-19 08:49) [23]

Neket   (18.11.07 09:57) [22]

> select
> name,
> avg(value)  OVER (ORDER BY value rows BETWEEN 1  PRECEDING
> AND CURRENT ROW) as value_avg
> from
> tabel1

без использования partition by результат, в общем случае, будет не тот, что Вам нужен


 
Кщд ©   (2007-11-19 08:59) [24]

если так сильно хочется аналитики, то

with t as (
select 1 as ID, 1 as val from dual
union all
select 1 as ID, 2 as val from dual
union all
select 1 as ID, 3 as val from dual
union all
select 2 as ID, 1 as val from dual
union all
select 2 as ID, 2 as val from dual
)
select *
from
(
select id,
      avg(val) over (partition by id order by val) avg_val,
      row_number() over(partition by id order by val) rn,
      count(*) over (partition by id) cnt
from t
) t2
where t2.rn = 1
     and t2.cnt = 2


 
Neket   (2007-11-19 14:54) [25]

Все всем спасибо... Все сделал. Все заработало.


 
Кщд ©   (2007-11-20 09:22) [26]

>Neket   (19.11.07 14:54) [25]
ради интереса: можно увидеть финальный вариант?


 
имя   (2007-11-24 21:26) [27]

Удалено модератором


 
Andrey ©   (2007-11-26 09:33) [28]

select t1.name,
      (select avg(t2.value)
         from tbl t2
        where t2.name = t1.name
          and rownum <= 2
        order by t2.value desc)
 from tbl t1
group by t1.name

Нэ?
Хотя конечно через хранимую лучше будет.


 
Кщд ©   (2007-11-27 10:47) [29]

>Andrey ©   (26.11.07 09:33) [28]
>and rownum <= 2
в общем случае, запрос будет возвращать ерунду)


 
Кщд ©   (2007-11-27 10:51) [30]

поясню - выполните:
[
select rownum, t2.*
        from tbl t2
       order by t2.value desc
]


 
Andrey ©   (2007-11-27 11:34) [31]

>Кщд ©   (27.11.07 10:51) [30]
Ыть, промазал. Никогда особо не использовал rownum, по этому не знал некоторых тонкостей: "Значение ROWNUM присваивается строке после завершения фазы обработки предикатов запроса, но перед выполнением каких-либо сортировок и агрегирований" http://www.oracle.com/global/ru/oramag/mayjune2007/w_dev_asktom56.html


 
Кщд ©   (2007-11-27 12:35) [32]

>Andrey ©   (26.11.07 09:33) [28]
теперь самое время подумать о кол-ве FTS)



Страницы: 1 вся ветка

Текущий архив: 2008.04.20;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.023 c
15-1204887995
Igor_
2008-03-07 14:06
2008.04.20
define для определения версии C++ Builder


15-1205136120
Jimmy
2008-03-10 11:02
2008.04.20
DVD и Dolby Digital 5.1


2-1206480203
VR
2008-03-26 00:23
2008.04.20
степень


2-1206269459
bagos
2008-03-23 13:50
2008.04.20
idhttp and asp


15-1204627499
tytus
2008-03-04 13:44
2008.04.20
Посоветуйте прогу обнаружения шпионов и Downloader-ов