Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
 Посчитать разницу строк с помощью триггера в sql server  [new]
ilnarinho
Member

Откуда:
Сообщений: 10
С помощью обычного запроса все работает:

SELECT nomer, sal, a2.sal-a1.sal AS total
FROM narabotka1 AS a1, narabotka1 AS a2
WHERE a1.nomer+1=a2.nomer
ORDER BY a1.nomer

Результат:
nomer___sal1__total
0________0____4
1________4____6
2________10___15
3________25___5
4________30___50
5________80___20
6________100__50
7________150__0
Не могу сделать с помощью триггера, чтобы он сам при добавлении строки в таблицу подсчитывал разницу между ноjой и старой строкой стоkбца sal. Может можно вместо триггера использовать что то другое?
18 апр 12, 12:53    [12432504]     Ответить | Цитировать Сообщить модератору
 Re: Посчитать разницу строк с помощью триггера в sql server  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
ilnarinho
С помощью обычного запроса все работает:
SELECT	 a1.nomer
	,a1.sal
	,a2.sal-a1.sal	AS total
FROM	     dbo.narabotka1	AS a1
	JOIN dbo.narabotka1	AS a2 ON a2.nomer = a1.nomer + 1
ORDER BY a1.nomer
Результат:
nomersal1total
004
146
21015
3255
43050
58020
610050
71500
Не могу сделать с помощью триггера, чтобы он сам при добавлении строки в таблицу подсчитывал разницу между ноjой и старой строкой стоkбца sal. Может можно вместо триггера использовать что то другое?
А чем вас запрос не устраивает?
CREATE VIEW dbo.vwNarabotka1Diff AS
SELECT	 a1.nomer
	,a1.sal
	,a2.sal-a1.sal	AS total
FROM	     dbo.narabotka1	AS a1
	JOIN dbo.narabotka1	AS a2 ON a2.nomer = a1.nomer + 1
GO
19 апр 12, 10:16    [12437444]     Ответить | Цитировать Сообщить модератору
 Re: Посчитать разницу строк с помощью триггера в sql server  [new]
ilnarinho
Member

Откуда:
Сообщений: 10
[/quot]А чем вас запрос не устраивает?
CREATE VIEW dbo.vwNarabotka1Diff AS
SELECT	 a1.nomer
	,a1.sal
	,a2.sal-a1.sal	AS total
FROM	     dbo.narabotka1	AS a1
	JOIN dbo.narabotka1	AS a2 ON a2.nomer = a1.nomer + 1
GO
[/quot]

А тем что каждый час добавляется новая строка и новое значение столбца "sal". Как в это случае будет обновляться таблица и подсчитываться столбец "total". Ведь с помощью запроса это делаться не будет!!
19 апр 12, 12:06    [12438215]     Ответить | Цитировать Сообщить модератору
 Re: Посчитать разницу строк с помощью триггера в sql server  [new]
iljy
Member

Откуда:
Сообщений: 8711
ilnarinho,

хорошо, сделайте с помощью триггера на insert (возможно еще на update?), проблема-то в чем?
19 апр 12, 12:11    [12438239]     Ответить | Цитировать Сообщить модератору
 Re: Посчитать разницу строк с помощью триггера в sql server  [new]
ilnarinho
Member

Откуда:
Сообщений: 10
iljy,
Добавил столбец ALTER TABLE narabotka1 ADD total integer NULL


CREATE TRIGGER TR_narabotka1 on narabotka1
AFTER INSERT AS
BEGIN
NEW.total = NEW.sal - OLD.sal
END

Выдает ошибку: Line 4: Incorrect syntax near "NEW"
19 апр 12, 12:50    [12438519]     Ответить | Цитировать Сообщить модератору
 Re: Посчитать разницу строк с помощью триггера в sql server  [new]
iljy
Member

Откуда:
Сообщений: 8711
ilnarinho
iljy,
Добавил столбец ALTER TABLE narabotka1 ADD total integer NULL


CREATE TRIGGER TR_narabotka1 on narabotka1
AFTER INSERT AS
BEGIN
NEW.total = NEW.sal - OLD.sal
END

Выдает ошибку: Line 4: Incorrect syntax near "NEW"

клево, а вы синтаксис не пытались изучить?
19 апр 12, 12:59    [12438592]     Ответить | Цитировать Сообщить модератору
 Re: Посчитать разницу строк с помощью триггера в sql server  [new]
iljy
Member

Откуда:
Сообщений: 8711
ilnarinho,

хотя конечно проблема тут не в синтаксисе, а в абсолютном непонимании даже основ реляционных БД. С ораклом раньше баловались?
19 апр 12, 13:01    [12438603]     Ответить | Цитировать Сообщить модератору
 Re: Посчитать разницу строк с помощью триггера в sql server  [new]
ilnarinho
Member

Откуда:
Сообщений: 10
iljy, да. немного знаком с Oracle. Не понятно в MSSQL как обратиться к старому и новому значению столбца?
19 апр 12, 14:19    [12439441]     Ответить | Цитировать Сообщить модератору
 Re: Посчитать разницу строк с помощью триггера в sql server  [new]
iljy
Member

Откуда:
Сообщений: 8711
ilnarinho
iljy, да. немного знаком с Oracle.

Это заметно.

ilnarinho
Не понятно в MSSQL как обратиться к старому и новому значению столбца?

Откуда у вас возьмется СТАРОЕ значение для ТОЛЬКО ЧТО ВСТАВЛЕННОЙ строки?? А вставленные строки находятся в псевдотаблице inserted.
19 апр 12, 14:23    [12439494]     Ответить | Цитировать Сообщить модератору
 Re: Посчитать разницу строк с помощью триггера в sql server  [new]
ilnarinho
Member

Откуда:
Сообщений: 10
iljy, Имел ввиду предыдущее значение и новое
19 апр 12, 14:34    [12439627]     Ответить | Цитировать Сообщить модератору
 Re: Посчитать разницу строк с помощью триггера в sql server  [new]
iap
Member

Откуда: Москва
Сообщений: 47145
ilnarinho
iljy, Имел ввиду предыдущее значение и новое
Этих значений много.
Столько, сколько строк вставили/проапдейтили командой INSERT/UPDATE.
Все новые значения строк - в inserted.
Все старые значения строк - в deleted.
deleted и inserted по структуре совпадают с таблицей
19 апр 12, 14:47    [12439726]     Ответить | Цитировать Сообщить модератору
 Re: Посчитать разницу строк с помощью триггера в sql server  [new]
iljy
Member

Откуда:
Сообщений: 8711
ilnarinho
iljy, Имел ввиду предыдущее значение и новое

Предыдущее значение находится в таблице, соответственно его надо из нее вытащить.
19 апр 12, 14:50    [12439760]     Ответить | Цитировать Сообщить модератору
 Re: Посчитать разницу строк с помощью триггера в sql server  [new]
iap
Member

Откуда: Москва
Сообщений: 47145
iljy
ilnarinho
iljy, Имел ввиду предыдущее значение и новое

Предыдущее значение находится в таблице, соответственно его надо из нее вытащить.
Не всегда.
Для триггеров AFTER в таблице находятся уже новые значения
19 апр 12, 14:55    [12439803]     Ответить | Цитировать Сообщить модератору
 Re: Посчитать разницу строк с помощью триггера в sql server  [new]
ilnarinho
Member

Откуда:
Сообщений: 10
iap, iljy, Спасибо за помощь. Сейчас попробую разобраться
19 апр 12, 14:57    [12439819]     Ответить | Цитировать Сообщить модератору
 Re: Посчитать разницу строк с помощью триггера в sql server  [new]
iljy
Member

Откуда:
Сообщений: 8711
iap
iljy
пропущено...

Предыдущее значение находится в таблице, соответственно его надо из нее вытащить.
Не всегда.
Для триггеров AFTER в таблице находятся уже новые значения

Для ТС "предыдущее значение" - это значение в строке с ID-1.
19 апр 12, 15:02    [12439881]     Ответить | Цитировать Сообщить модератору
 Re: Посчитать разницу строк с помощью триггера в sql server  [new]
iap
Member

Откуда: Москва
Сообщений: 47145
iljy
iap
пропущено...
Не всегда.
Для триггеров AFTER в таблице находятся уже новые значения

Для ТС "предыдущее значение" - это значение в строке с ID-1.
Получается, я тут вообще не по делу высказывался...
19 апр 12, 15:06    [12439915]     Ответить | Цитировать Сообщить модератору
 Re: Посчитать разницу строк с помощью триггера в sql server  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
ilnarinho
Как в это случае будет обновляться таблица и подсчитываться столбец "total".
А зачем он в таблице?
DECLARE	@Table TABLE (
	 ID	Int	IDENTITY PRIMARY KEY
	,[Date]	Date	NOT NULL DEFAULT (GetDate()) UNIQUE
	,Amount	Money	NOT NULL
)
INSERT	@Table VALUES
 ('20120101',1.23)
,('20120201',3.45)
,('20120301',6.78)
,('20120501',9.01)
-----------------------------------------------------------
SELECT	*,Sum(Amount)OVER(ORDER BY [Date]) AS Total
FROM	@Table
"Текущий остаток" можно отдельно хранить, для оперативного дня(ей), к примеру. Но для каждой операции, что-то жирновато как-то.

Особенно офигитительно выглядит следующее:
TimeAmountTotal
12:151010
12:17-28
13:01411
14:07516
Когда корявая система, от неровных рук, то и контроль данных корявый, а данные - мусор.
19 апр 12, 16:08    [12440564]     Ответить | Цитировать Сообщить модератору
 Re: Посчитать разницу строк с помощью триггера в sql server  [new]
ilnarinho
Member

Откуда:
Сообщений: 10
Mnior,
А в чем разница? Почему нельзя в той же таблице хранить данные total. А значения total нужны для статистики и должны каждый час рассчитываться автоматически
19 апр 12, 17:30    [12441225]     Ответить | Цитировать Сообщить модератору
 Re: Посчитать разницу строк с помощью триггера в sql server  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
ilnarinho
Почему нельзя в той же таблице хранить данные total.
Потому что не отвечает на вопрос "Зачем хранить?".
ilnarinho
А значения total нужны для статистики
Эээ, какой это статистики нужно всегда хранить для каждой операции?
ilnarinho
должны каждый час рассчитываться автоматически
1. Для чего?
2. каждый час - это не для каждой строки
3. каждый час - это т.е. если в системе 10000 "счетов", то за 10 лет вы должны хранить 10000*10*365*24 строк? 90% из которых практически дублируются. Мне кажется даже операций будет меньше.

каждый час - это какая-то надуманная бизнес задача. Не?

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

PS: Разработчик не может неправильно выражать смысл.

КО
19 апр 12, 22:20    [12442597]     Ответить | Цитировать Сообщить модератору
 Re: Посчитать разницу строк с помощью триггера в sql server  [new]
Сергей Мишин
Member

Откуда:
Сообщений: 376
Mnior
...
Не могу придумать такой задачи при которой нужно постоянно вытягивать из системы Total для каждой операции по всей истории.
...

Типичный пример: выписка с банковского счета, сумма транзакции и депозит до, после.

ilnarinho,
Решений много, триггер, обновлять отдельно поcле вставки строк и т.д.. Чтоб ответить на Ваш вопрос правильно, надо знать как обновляются данные, что за данные, по одной записи, пачкой или там вообще bulk insert
20 апр 12, 02:52    [12443258]     Ответить | Цитировать Сообщить модератору
 Re: Посчитать разницу строк с помощью триггера в sql server  [new]
ilnarinho
Member

Откуда:
Сообщений: 10
Mnior, Ваше утверждение имеет право на жизнь. Да, моя база избыточная, но она влияет только на размер самой базы. Меня же интересует скорость вычисления данных. И как мне кажется при постоянном пересчете будет не удобно постоянно ждать.


Mnior
2. каждый час - это не для каждой строки
3. каждый час - это т.е. если в системе 10000 "счетов", то за 10 лет вы должны хранить 10000*10*365*24 строк? 90% из которых практически дублируются.

Дублирование данных не будет, строка добавляется один раз в час
Но мне как раз не нужен постоянный пересчет, он происходит медленно. Этих totalов в моей базе около 10.
Базу можно ограничить 1 - 2 годами. Но дело не в это. Размер базы не сильно важен. Я же думаю сделать как можно лучше.

Mnior
каждый час - это какая-то надуманная бизнес задача. Не?

TOTAL - Это количество воды, пройденное за каждый час.
20 апр 12, 12:16    [12444734]     Ответить | Цитировать Сообщить модератору
 Re: Посчитать разницу строк с помощью триггера в sql server  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
ilnarinho
И как мне кажется при постоянном пересчете будет не удобно постоянно ждать.
Я вам могу придумать пример когда перерасчёт будет работать быстрее.
Самое простое объясненние. Чем меньше данных на дисках тем существенне быстрее их считать. Процы в основном простаиваю. Даже на заруженных корпоративных серверах. Проблема чаще в IO.
В добавок, порядок чтения данных очень важен (Stream Merge против Loop Seek).

ilnarinho
Дублирование данных не будет, строка добавляется один раз в час
TOTAL - Это количество воды, пройденное за каждый час.
И если вода не течёт, то строки будут дублируются (естественно кроме поля [время]).

ilnarinho
Но мне как раз не нужен постоянный пересчет, он происходит медленно.
А у вас есть постоянный перерасчёт?
Врёте. Нет таких задач при которых надо перерасчитывать каждый час все строки в базе.

ilnarinho
Я же думаю сделать как можно лучше.
Я к тому же. Ожидания среднего разработчика с вероятностью 90% неверны. Нормальный человек верит, нормальный IT разработчик знает. Обычный человек не любит включать мозг. Он лучше будет верить во что-то простое (деже еесли это иногда не верно), лишь бы не думать.
Просто "считаете" или можете доказать - это совершенно разные вещи.

ilnarinho, и после всё сказанного вами, я всё ещё уверен, что вы недопонимаете осной посыл и глубину проблемы понимания.

Ok. Давайте как 3х летнему.
Имеем. БД за 3 года (неважно).
Скажите. Сколько раз за последний месяц будет обращений с записям по воде на 2 года назад?
Когда, к каким данным и как часто будут обращения (чтения)?

Если 99% будут обращения к последней записи (к текущим показателям), то хранить надо только эти текущие показатели.
Еслу у вас будут отчёты (Total, Avg и т.п.) за период (день, месяц, год). То вы может хранить только эти уже агрегированные данные (через индексированные представления, например).

Вы должны понять всю проблематику и сознательно решить, что хранение (не) лучше в данном случае при данных условиях.
Например, очень важен показатель простоты системы. Но я очень часто видел что хранятся промежуточные данные, при этом тупо удалив излишние колонки и таблицы и упростив запросы, работать стало существенно быстрее и решилось море багов.

Хранение промежуточных данных - не панацея, не правило, и даже не "желательно". Лучше подумать.

PS: Вас я не заставляю и не утверждаю, что хранение промежуточных данных зло. Просто приглашаю к сознательному пониманию и учёту многих тонкостей проектирования.
20 апр 12, 16:09    [12446854]     Ответить | Цитировать Сообщить модератору
 Re: Посчитать разницу строк с помощью триггера в sql server  [new]
ilnarinho
Member

Откуда:
Сообщений: 10
Mnior
А у вас есть постоянный перерасчёт?
Врёте. Нет таких задач при которых надо перерасчитывать каждый час все строки в базе.


Не требуется пересчитывать все строки, можно подсчитывать только значение total в последней строке как разность последнего и предыдущего значения sal.
20 апр 12, 17:38    [12447638]     Ответить | Цитировать Сообщить модератору
 Re: Посчитать разницу строк с помощью триггера в sql server  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6724
ilnarinho
Не требуется пересчитывать все строки, можно подсчитывать только значение total в последней строке как разность последнего и предыдущего значения sal.
Mnior
Если 99% будут обращения к последней записи (к текущим показателям), то хранить надо только эти текущие показатели.
Ну вот.
CREATE TRIGGER [trMeterIncrementationModify] ON [dbo].[MeterIncrementation]
AFTER INSERT,UPDATE,DELETE AS BEGIN
	SET NOCOUNT ON

	UPDATE	M
	SET	[Current]	+= IsNull(I.Increment,0)
				 - IsNull(D.Increment,0)
	FROM	          Inserted	I
		FULL JOIN Deleted	D ON D.ID = I.ID
		     JOIN dbo.Meter	M ON C.ID = IsNull(I.Meter,D.Meter)
END
GO
SELECT	 I.*
	,M.[Current] - Sum(I.Increment)OVER(PARTITION BY I.Meter ORDER BY I.[Time])	AS Total
FROM	     dbo.MeterIncrementation	I
	JOIN dbo.Meter			M ON M.ID = I.Meter
20 апр 12, 18:56    [12448026]     Ответить | Цитировать Сообщить модератору
 Re: Посчитать разницу строк с помощью триггера в sql server  [new]
Chkot
Guest
Зачем заморачиваться с тригером?
рассчитывайте значение колонки при вставке
20 апр 12, 21:16    [12448534]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить