Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Хранимая процедура


Страницы:   1 2 3

Knight ©   (2008-06-17 09:01:00) 

Помогите осознать логику процедуры, которая должена сделать выборку из двух таблиц.

В результирующий набор данных должны попасть строки из табл1 для которых табл1.поле1=табл2.поле1 AND табл2.поле2=0 ... или табл1.поле1 попадает в интервал значений табл2.поле1 такой, что хотя бы один из них имеет табл2.поле2=0

табл1
---------------------
   поле1     поле2
---------------------
1  |  1   | значение1
2  |  4   | значение2
3  |  6   | значение3
4  |  7   | значение4
5  |  14  | значение5

табл2
---------------------
   поле1     поле2
---------------------
1  |  2   | 23
2  |  5   | 0
3  |  7   | 0
4  |  9   | 2322
5  |  11  | 111
6  |  13  | 232
7  |  15  | 0


ЮЮ   (2008-06-20 04:12:00) [1]

> [51] Knight ©   (19.06.08 22:11)
> Спасибо, завтра погляжу… чёт сёдня приболел.


Не забудь в SELECT-ах курсоров … AND(ObjID = @ObjID) ORDER BY  ttime


Knight   (2008-06-19 22:11:00) [2]

> [49] ЮЮ ©   (19.06.08 10:15)

Спасибо, завтра погляжу.. чёт сёдня приболел.


ANB   (2008-06-19 18:49:00) [3]


> Надо отловить только те показания первого датчика во время
> снятия которых
значения второго были нулевые.


Вот это условие мона расшифровать поподробнее ? И я совершенно не пронаблюдал интервалов. Есть только точки.

Я бы понял задачу так :

Нужно вывести все значения таблицы2 (показаний второго датчика). Если же какое то значение поля "Показание датчика" таблицы2 равно 0, то заменить его соответствующим значением из таблицы1, причем найти в ней строку, ближайщую по времени (Т1.поле1) к времени измерения второго датчика (Т2.поле1).

Так ?


ЮЮ   (2008-06-19 10:15:00) [4]

>
> [0] Knight ©   (17.06.08 09:01)
> Помогите осознать логику процедуры, которая должена сделать
> выборку из двух таблиц.


Через 3 с половиной часа телепетор уловил мысль. Автор продолжает «шифроваться»

> [34] ЮЮ ©   (17.06.08 12:38)
> Хочется
> «проредить» table1, оставив те записи, пока взведен флаг
> «в table2 все ещё стоит 0»



Телепатор перегревается и требует подтверждений своих догадок


> [42] ЮЮ ©   (18.06.08 06:13)
> ты хочешь получить только
> те показания первого, когда показания второго уже нулевые
> или станут нулевыми при следующем измерении?


Через сутки автор сдается

> [48] Knight ©   (18.06.08 10:40)
> Надо отловить
> только те показания первого датчика во время снятия которых
> значения второго были нулевые.


И это свои, не один год здесь обитающие. А мы ещё от новичков чего-то требуем.

Теперь по subj-у. Где-то так:

CREATE FUNCTION GetBlaBla(
@ObjID INT,
@TimeStart datetime,
@TimeEnd datetime
)
RETURNS @Result TABLE(ttime datetime, v1 int) AS
BEGIN

 DECLARE c1 CURSOR LOCAL FOR
   SELECT ttime, v1 FROM T1 WHERE ttime BETWEEN @TimeStart AND @TimeEnd
 OPEN c1

 DECLARE c2 CURSOR LOCAL FOR
   SELECT ttime, v2 FROM T2 WHERE ttime BETWEEN @TimeStart AND @TimeEnd
 OPEN c2

 DECLARE @t2Before datetime, @v2Before int
 DECLARE @t2After  datetime, @v2After int
 DECLARE @t1  datetime, @v1 int

 FETCH NEXT FROM c2 INTO @t2After, @v2After
 IF @@FETCH_STATUS = —1 BEGIN
   —— нет показаний в t2
   INSERT INTO @Resul
     SELECT ttime, v1 FROM T1 WHERE ttime BETWEEN @TimeStart AND @TimeEnd
   RETURN
 END

 SET @v2Before = 0
 FETCH NEXT FROM c1 INTO @t1, @v1
 WHILE @@FETCH_STATUS —1 BEGIN
   IF @@FETCH_STATUS = 0 BEGIN
     —— продвинемся по T2 до тех пор, пока не достигнем того, что
     —— текущая запись добавлена не позже, а предудущая раньще времени записи в T1

     WHILE @t2After < @t1 BEGIN
       SET @t2Before = @t2After
       SET @v2Before = @v2After  
       FETCH NEXT FROM c2 INTO @t2After, @v2After
       IF @@FETCH_STATUS = —1 BEGIN
         —— считаем, что до конца периода стоит 0
         SET @t2After = @TimeEnd + 0.01
         SET @v2After = 0
       END
     END

     IF (@v2After = 0) OR (@v2Before = 0)
       INSERT INTO @Resul SELECT @t1, @v1

     FETCH NEXT FROM c1 INTO @t1, @v1
   END
 END
 RETURN
END


Knight   (2008-06-18 10:40:00) [5]

> [47] ANB   (18.06.08 10:32)

поле1 в табл1 и табл2 практически не имеет общих значений... интервалы занесения показаний датчиков разные. Надо отловить только те показания первого датчика во время снятия которых значения второго были нулевые.


ANB   (2008-06-18 10:32:00) [6]


> или табл1.поле1 попадает в интервал значений табл2.поле1
> такой, что хотя бы один из них имеет табл2.поле2=0

Переведи. Как определить интервал (я так понял это between ?), если подходящих значений табл2.поле1 15 ?

Если же вопрос стоит так : выбрать все записи из табл1, у которых табл1.поле1 входит в набор табл2.поле1 при табл2.поле2=0
то запрос выглядит так :


select
T1.поле1
,T1.поле2
from
табл1 T1
where
  табл1.поле1 in
(
selecty табл2.поле1
from табл2 T2
where табл2.поле2 = 0
)


Но такой запрос при больших таблицах будет довольно медленным. Мой делает тоже самое, но быстрее.


Knight   (2008-06-18 10:26:00) [7]

> [45] ANB   (18.06.08 10:21)
> или табл1.поле1 попадает в интервал значений табл2.поле1
> такой, что хотя бы один из них имеет табл2.поле2=0

илитабл1.поле1 попадает в интервал значений табл2.поле1 такой, что хотя бы один из них имеет табл2.поле2=0


ANB   (2008-06-18 10:21:00) [8]

В результирующий набор данных должны попасть строки из табл1 для которых табл1.поле1=табл2.поле1AND табл2.поле2=0 ... или табл1.поле1 попадает в интервал значений табл2.поле1 такой, что хотя бы один из них имеет табл2.поле2=0

???


Knight   (2008-06-18 08:34:00) [9]

> [42] ЮЮ ©   (18.06.08 06:13)

Какая структура организует цикл в sql?


Knight   (2008-06-18 08:29:00) [10]

> [41] ANB   (17.06.08 22:34)
> табл2.поле1 = табл1.поле1

Нет там равенства полей :(


ЮЮ   (2008-06-18 06:13:00) [11]

> [37] Knight ©   (17.06.08 13:03)
>
> Когда показания второго нулевые, то показания первого точнее.


Но когда показания второго ненулевые, их вообще нет в выборке.

И все-таки, что ты хочеь получить теперь, когда стало понятно, что в таблицы пишутся показания с двух датчиков, причём не зависимо друг от друга.

Из твоих попытот следует, что ты хочешь получить только те показания первого, когда показания второго уже нулевые или станут нулевыми при следующем измерении?

З.Ы. Я веду это к тому, что цикл по курсору, ИМХО будет быстрее и «прозрачее», чем EXISTS и агрегирующие подзапросы.


ANB   (2008-06-17 22:34:00) [12]


select
 /*+ full(T1) full(T2) parallel(T1,4) parallel(T2,4) use_hash(T1,T2) */
 distinct
 T1.поле1
,T1.поле2
from
 табл1 T1
,табл2 T2
where
   табл2.поле1 = табл1.поле1
and табл2.поле2 = 0


Если я правильно перевел условие, то так должно работать.
Если в каждой таблице по миллиону записей, то у меня отработало за 5 мин.


ANB   (2008-06-17 22:28:00) [13]


> Они обе ОЧЕНЬ большие.

Скока миллионов записей ?


Knight   (2008-06-17 16:37:00) [14]

Напартачил... идёт просто выборка всех записей за период из Т1


Knight   (2008-06-17 16:08:00) [15]

Переделал... вот так стало
за 1 день 0.3 мин
за 5 дней 1.6 мин.

Мож кто проверит не напартачил ли чего? %)

T1 - ttime, v1
T2 - ttime, v2

CREATE PROCEDURE GetBlaBla(
 @ObjID INT,
 @TimeStart datetime,
 @TimeEnd datetime
)
AS
BEGIN
 /* Procedure body */
                   
 DECLARE @Max datetime
 DECLARE @Min datetime
 
 SET @Max=(SELECT MIN(ttime) FROM T2 WHERE ttime>=@TimeEnd AND ObjID=@ObjID)
 SET @Min=(SELECT MAX(ttime) FROM T2 WHERE ttime<=@TimeStart AND ObjID=@ObjID)
 
 SELECT a.ttime, a.v1))
  FROM T1 a
     WHERE a.ttime BETWEEN @TimeStart AND @TimeEnd
       AND a.ObjID=@ObjID
       AND exists(SELECT 1 FROM T2
        WHERE ttime
             BETWEEN (Select MAX(ttime) FROM T2 WHERE ttime<=a.ttime AND ObjID=@ObjID)
        AND (Select MIN(ttime) FROM T2 WHERE ttime>=a.ttime AND ObjID=@ObjID)
           AND v2=0 AND ObjID=@ObjID AND ttime BETWEEN @Min AND @Max)
END


Knight   (2008-06-17 13:03:00) [16]

> [36] ЮЮ ©   (17.06.08 12:59)

Когда показания второго нулевые, то показания первого точнее.


ЮЮ   (2008-06-17 12:59:00) [17]

> В таблицы пишутся показания с двух датчиков, причём не зависимо
> друг от друга.

А что ты хочешь показать? Почему показания только одного и только в те моменты, когда нет показаний другого?


Knight   (2008-06-17 12:49:00) [18]

В таблицы пишутся показания с двух датчиков, причём не зависимо друг от друга.


ЮЮ   (2008-06-17 12:38:00) [19]

> [31] Knight ©   (17.06.08 12:20)
> > [30] ЮЮ ©   (17.06.08 12:05)
>
> Поле1 datetime


По примеру и не догадаешься :)

Итак в определенные промежутки времкни еешьу записи пишутся
а) в table2 в формате
0 / не ноль

б) в table1 в формате
 какаое-то значение

в) в обе таблицы сразу.

Хочется
 «проредить» table1, оставив те записи, пока взведен флаг «в table2 все ещё стоит 0»

Тогда два цикла по двум курсорам. В во внешнем цикле по table1 «скользишь» по table2 до нужной записи в курсоре по table1 и взводишь/сбрасываешь флаг. В зависимости от его значения выводишь или нет записсь из table1 в результирующий НД.


> [29] Knight ©   (17.06.08 11:54)


> строка 1 значение — табл2.поле1
> строка   значение — табл1.поле1
> строка 2 значение — табл2.поле1


Учитывая это можно и в одном цикле по одному курсору, в запросе которого объединить записи из обких таблиц


Knight   (2008-06-17 12:27:00) [20]

IsZero работает 282 ms.

GetBlaBla
за день   0.11 мин.
за 5 дней 2.3 мин


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо