Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2008.04.20;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.53 MB
Время: 0.046 c
15-1204884874
matt
2008-03-07 13:14
2008.04.20
Exception Conference #07


4-1187348602
Ricks
2007-08-17 15:03
2008.04.20
Странное ограничение....


2-1204039868
nusik1990
2008-02-26 18:31
2008.04.20
ввод в TEdit


2-1206540539
Rus
2008-03-26 17:08
2008.04.20
Помогите раскрыть двоичный файл


2-1206368361
AlexeyMir
2008-03-24 17:19
2008.04.20
Кеширование в таблице Firebird





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский