Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Web программирование > SQL, базы данных
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 10.09.2013, 17:40   #1
mulatoschka1990
Пользователь
 
Аватар для mulatoschka1990
 
Регистрация: 23.10.2009
Сообщений: 12
По умолчанию

Доброго времени суток, уважаемые форумчане
Дана таблица Test

CREATE TABLE Test (
ID INT IDENTITY(1,1) NOT NULL,
Value INT NOT NULL
)

Задача такая: определить первую запись, начиная с которой сумма итога по столбцу Value превысит 1000

Весь мозг сломала, наведите пожалуйста как реализовать запрос

Решила вот таким образом, буду рада поправкам

Код:
select top 1 t2.id
from [People].[dbo].[Test] t2
left outer join [People].[dbo].[Test] t1 on t1.id < t2.id
group by t2.id
having sum(isnull(t1.Value, 0))+max(t2.Value) > 1000

Последний раз редактировалось Stilet; 11.09.2013 в 17:19.
mulatoschka1990 вне форума Ответить с цитированием
Старый 10.09.2013, 19:09   #2
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Ох и долго он будет работать для большой таблицы и больших значений оценочной константы. Если в лоб, то подправил бы так
Код:
select TOP 1 t2.id 
  from Test t2 
    left outer join Test t1 on t1.id <= t2.id 
  group by t2.id 
  having SUM(t1.Value) > 1000 
  ORDER BY t2.id
А вообще в современных версиях MS SQL куча новых возможностей и возможно используя их это можно сделать оптимальней
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 10.09.2013, 19:33   #3
mulatoschka1990
Пользователь
 
Аватар для mulatoschka1990
 
Регистрация: 23.10.2009
Сообщений: 12
По умолчанию

Спасибо большое!
Первый вариант уже отбросила)...теперь мне нужно как то заменить функцию TOP, чтоб запрос работал на SQL 92

Код:
select FIRST 1 t2.id 
  from Test t2 
    left outer join Test t1 on t1.id <= t2.id 
  group by t2.id 
  having SUM(t1.Value) > 1000 
  ORDER BY t2.id
если я не ошибаюсь FIRST n берет первые n записей из запроса и поддерживается sql92? http://savage.net.au/SQL/sql-92.bnf.html#xref-FIRST

А как можно оптимизировать запрос для MSSQL 2008?

Последний раз редактировалось Stilet; 11.09.2013 в 17:20.
mulatoschka1990 вне форума Ответить с цитированием
Старый 10.09.2013, 22:39   #4
Vapaamies
Ваш К. О.
Участник клуба
 
Аватар для Vapaamies
 
Регистрация: 26.12.2012
Сообщений: 1,767
По умолчанию

На самом деле тут нужно использовать аналитическую функцию и оконное выражение, -- что-то вроде rows between preceding and unbounded following. Боюсь, что для уровня вопрошающей это слишком круто, а мне сегодня думать лень.
Vapaamies вне форума Ответить с цитированием
Старый 11.09.2013, 00:00   #5
mulatoschka1990
Пользователь
 
Аватар для mulatoschka1990
 
Регистрация: 23.10.2009
Сообщений: 12
По умолчанию

Vapaamies, спасибо за ответ

Главное условие моего задания - "Задача решается без курсоров, на чистом SQL-92"
А ваше решение больше подходит для оракл и sql 92 не поддерживает указанные функии.

Вторым пунктом мне нужно написать этот же запрос для MSSQL более оптимальным способом.

Последний раз редактировалось mulatoschka1990; 11.09.2013 в 00:03.
mulatoschka1990 вне форума Ответить с цитированием
Старый 11.09.2013, 01:35   #6
Vapaamies
Ваш К. О.
Участник клуба
 
Аватар для Vapaamies
 
Регистрация: 26.12.2012
Сообщений: 1,767
По умолчанию

Цитата:
Сообщение от mulatoschka1990 Посмотреть сообщение
А ваше решение больше подходит для оракл и sql 92 не поддерживает указанные функии.
А теперь смотрим, как оно на самом деле. Я сегодня в роли Капитана Очевидность.

Не уверен, правда, что аналитические функции входят именно в стандарт SQL-92, но поддерживаются несколькими СУБД -- это точно. И решают задачу без курсора и алгоритмики, -- это тоже не вызывает сомнений. И на практике применяются. Ваш К. О.
Vapaamies вне форума Ответить с цитированием
Старый 11.09.2013, 13:35   #7
mulatoschka1990
Пользователь
 
Аватар для mulatoschka1990
 
Регистрация: 23.10.2009
Сообщений: 12
По умолчанию

Vapaamies, описание предложения OVER по вашей ссылке для MSSQL 2012.
Там моя задача решалась бы так?

Код:
SELECT TOP 1 t_out.ID FROM
 (SELECT ID, (SUM(Value) OVER (ORDER by ID)) AS summ FROM [TestDB].[dbo].[Test]) AS t_out
WHERE t_out.summ > 1000
Мне же нужно представить решение на чистом SQL 92 и для MSSQL 2008.

Для SQL 92 вот такой запрос:
Код:
SELECT MIN(t_out.ID) FROM
(
	SELECT t.ID
FROM #Test  t
JOIN #Test  t1 ON (t1.id <= t.id)
GROUP BY t.id
HAVING SUM(t1.Value) > 1000
ORDER BY t.id
) as t_out


Для mssql 2008 2 варианта:
1.
Код:
SELECT TOP 1 t_out.ID FROM
	(SELECT DISTINCT t.id, SUM(t1.Value) OVER (PARTITION BY t.id ) as summ
	FROM [TestDB].[dbo].[Test] t
	JOIN [TestDB].[dbo].[Test] t1 ON (t1.id <= t.id)
	) AS t_out
WHERE t_out.summ > 1000
2.
Код:
SELECT TOP 1 * FROM
(SELECT t2.id,
	(
	SELECT SUM(t1.Value)
	FROM [TestDB].[dbo].[Test] t1
	WHERE t1.id<=t2.id 
	) AS summ
FROM [TestDB].[dbo].[Test] t2) AS t
WHERE t.summ > 1000
Причем второй оказался быстрее

Я очень буду рада критике и наставлениям))))))
mulatoschka1990 вне форума Ответить с цитированием
Старый 11.09.2013, 16:51   #8
Vapaamies
Ваш К. О.
Участник клуба
 
Аватар для Vapaamies
 
Регистрация: 26.12.2012
Сообщений: 1,767
По умолчанию

Цитата:
Сообщение от mulatoschka1990 Посмотреть сообщение
Причем второй оказался быстрее
И правильно, ибо использовать distinct вместе с аналитической функцией -- маразм.

Если MS SQL 2008 не поддерживает конструкцию rows between -- то самое оконное выражение, посоветовать что-то другое не могу. Я вообще не спец по MS SQL.
Vapaamies вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
нарастающий итог с учетом фактического результата zemlyanukhina Microsoft Office Excel 2 22.02.2011 09:16
Запрос с CASE переделать в запрос с PIVOT (MS SQL Server 2005) Машуля SQL, базы данных 4 06.05.2010 21:09
Создание новых таблиц в MS SQL SERVERE через SQL запрос в Delphi S_Yevgeniy Помощь студентам 1 27.10.2009 06:26
SQL запрос на основе другого SQL запрса... Timoxa БД в Delphi 1 07.01.2007 18:15
нарастающий итог SerGo БД в Delphi 1 10.11.2006 10:08