Помогите, пож., правильно составить процедурку
Релиб
Форумы       Участники    Календарь    Кто он-лайн?
Добро пожаловать, гость ( Вход | Регистрация )
        


12»»

Помогите, пож., правильно составить... Expand / Collapse
Автор
Сообщение
09.10.2006 13:52


Supreme Being

Supreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme Being

участник
Last Login: 20.02.2009 9:10
Сообщ.: 275, Visits: 867
Здравствуйте!
Помогите, пож., правильно составить процедурку.
У меня есть таблица, в которой имеется поле Name (Имя), DateT(Дата) и поле Cnt (Количество).
В таблицу постоянно заносятся данные.
Также имеется еще одна таблица, у которой поля: DateT(Дата) и все Name какие есть в первой таблице.
Мне нужно сделать процедуру, которая считает для каждого Name из первой таблицы общее количество за день, а результат должен заносится во вторую таблицу.

Что-то такое:

tbl1
Name | DateT | Cnt
--------------------
Вася | 01.09.2006 | 3
Петя | 01.09.2006 | 2
Вася | 02.09.2006 | 3
Петя | 02.09.2006 | 7
Вася | 02.09.2006 | 5

tbl2
DateT | Вася | Петя
--------------------
01.09.2006 | 3 | 2
02.09.2006 | 8 | 7
Сообщ. #905459
09.10.2006 14:11


Supreme Being

Supreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme Being

модератор
Last Login: 29.10.2007 14:45
Сообщ.: 1 833, Visits: 16 863
Если все именно так, как ввы напсиали (т.е. во второй таблице есть поля Вася и Петя, а не Name), то запрос будет таким:

SELECT

      DateT,

      sum(case when  'Вася' then cnt else 0 end) Вася,

      sum(case when  'Петя' then cnt else 0 end) Петя,

 

FROM Tbl

GROUP BY DateT

 

В другом варианте, когда структура второй таблицу вот такая (DateT, Name, Quan), то будет такой запрос:

 

SELECT DateT, Name, Sum(cnt) Cnt

FROM Tbl

GROUP BY DateT, Name

Есть еще один способ - использовать оператор PIVOT, однако он действителен только для 2005 сервера.

Сообщ. #905462
09.10.2006 14:16


Supreme Being

Supreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme Being

участник
Last Login: 20.02.2009 9:10
Сообщ.: 275, Visits: 867
У меня первый вариант.

Т.е. когда имена будут добавляться, то и процедуру придется менять? Я думал можно как-нибудь в цикле это сделать.
Сообщ. #905463
09.10.2006 14:29


Supreme Being

Supreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme Being

модератор
Last Login: 29.10.2007 14:45
Сообщ.: 1 833, Visits: 16 863
Можно и в цикле и при помощи PIVOT.

Однако, какая необходимость создавать для каждого имени свой столбец? Это глупость, на мой взгляд.

Сообщ. #905466
09.10.2006 14:34
Supreme Being

Supreme Being

модератор
Last Login: 04.05.2008 13:32
Сообщ.: 7 234, Visits: 65 445
Я бы шире вопрос поставил. Зачем вообще отдельная таблица? Ведь по сути она дублирует первую из которой с помощью sum/where/group by можно всегда получить нужную информацию.
Сообщ. #905468
09.10.2006 14:47


Supreme Being

Supreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme Being

участник
Last Login: 20.02.2009 9:10
Сообщ.: 275, Visits: 867
Я с вами полностью согласен, но мне поставили такую задачу :\

А как в SQL можно в цикле перебрать поля?
Сообщ. #905470
09.10.2006 14:51


Supreme Being

Supreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme Being

модератор
Last Login: 29.10.2007 14:45
Сообщ.: 1 833, Visits: 16 863
Хмм... а для каких целей, не объяснили? Это заранее неправильный подход для ХРАНЕНИЯ данных.

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

Сообщ. #905471
09.10.2006 14:59


Supreme Being

Supreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme Being

модератор
Last Login: 29.10.2007 14:45
Сообщ.: 1 833, Visits: 16 863
Перебрать поля можно, к примеру, так (если дальше будете динамический SQL использовать):

DECLARE @Fields varchar(1024)

SET @Fields =''

 

SELECT @Fields=@Fields + Name + ', '

FROM syscolumns

WHERE ID=(SELECT ID FROM sysobjects WHERE NAME='dom_our')

 

SET @Fields=Substring(@Fields,1, Len(@Fields)-1)

SELECT @Fields

 

 

Сообщ. #905473
09.10.2006 15:49


Supreme Being

Supreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme Being

участник
Last Login: 20.02.2009 9:10
Сообщ.: 275, Visits: 867
Это и будет своего рода отчет за день .
Сообщ. #905478
09.10.2006 16:00


Supreme Being

Supreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme Being

модератор
Last Login: 29.10.2007 14:45
Сообщ.: 1 833, Visits: 16 863
Тогда почитайте книжки по базам. Поверьте, полезно.
Сообщ. #905479
09.10.2006 16:14
Supreme Being

Supreme Being

модератор
Last Login: 04.05.2008 13:32
Сообщ.: 7 234, Visits: 65 445
Вот такой вариант с динамическим sql можно использовать.

SELECT SUM(cnt) nameCnt,
       name,
       DateT
       INTO   #t3
       FROM   tbl1
       WHERE  DateT = '02.09.2006'
GROUP BY Name, DateT

WHILE EXISTS (SELECT * FROM #t3)
BEGIN
   DECLARE @nameCnt int,
           @name varchar(100),
           @datet datetime
          
   SELECT TOP 1
          @nameCnt = nameCnt,
          @name = name,
          @datet = dateT
          FROM #t3
  
   DECLARE @SQLString nvarchar(500)
   SET @SQLString = 'UPDATE #tbl2 SET ['+@name+']=@cnt WHERE DateT=@DateT;'+
                    ' IF 0=@@ROWCOUNT INSERT INTO #tbl2 (DateT,['+@name+']) VALUES(@DateT, @cnt)'
   EXEC sp_executesql @SQLString, N'@DateT datetime, @cnt int', @DateT, @nameCnt
  
   DELETE FROM #t3
   WHERE name=@name AND dateT=@datet
END
DROP TABLE #t3

Сообщ. #905481
09.10.2006 16:16
Supreme Being

Supreme Being

модератор
Last Login: 04.05.2008 13:32
Сообщ.: 7 234, Visits: 65 445
Мда. Забыл пояснить. Данный код использует динамический sql чтобы не было нужно менять код когда в таблице tbl1 появятся новое имя, а в tbl2 соответствующее ей поле.

В первом SELECT надо сделать условоие чтобы выборка шли по текущей дате.

Сообщ. #905482
09.10.2006 16:30


Supreme Being

Supreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme Being

модератор
Last Login: 29.10.2007 14:45
Сообщ.: 1 833, Visits: 16 863
В свою очередь, мой экзампл для MS SQL2005:

CREATE TABLE History (Name varchar(100), DT datetime, Quan int)

 

INSERT INTO History VALUES ('Вася', '01.01.2005', 5)

INSERT INTO History VALUES ('Вася', '01.01.2005', 51)

INSERT INTO History VALUES ('Вася', '01.01.2005', 45)

INSERT INTO History VALUES ('Петя', '01.01.2005', 57)

INSERT INTO History VALUES ('Петя', '01.01.2005', 4)

INSERT INTO History VALUES ('Вася', '02.01.2005', 5)

INSERT INTO History VALUES ('Вася', '02.01.2005', 5)

INSERT INTO History VALUES ('Петя', '02.01.2005', 9)

 

SELECT *

FROM History h

PIVOT (Sum(Quan) FOR Name IN ([Вася], [Петя])) as pvt

 

DROP TABLE History

Для 2000 сервера можно сделать нечто подобное, если использовать специальные хранимые процедуры, к примеру, эту: http://www.sql.ru/faq/faq_topic.aspx?fid=358

Сообщ. #905483
10.10.2006 11:12


Supreme Being

Supreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme Being

участник
Last Login: 20.02.2009 9:10
Сообщ.: 275, Visits: 867
Спасибо большое! Исчерпывающе :)
Сообщ. #905510
11.10.2006 14:48


Supreme Being

Supreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme Being

участник
Last Login: 20.02.2009 9:10
Сообщ.: 275, Visits: 867
Еще вопрос:

Если мне нужно обновить какое-то поле в таблице, то я пишу так:

UPDATE tbl1 SET Ivan=57 FROM tbl1 WHERE DateT='09.02.2006'

А если я заранее не знаю как называется поле и только после всяких манипуляций узнаю, что поле называется Ivan и записано у меня это примерно так @name='Ivan', то как мне записать запрос на обновление?

Имя поля я узнал при таком запросе:

SELECT column_name, as Automat FROM [ХХХ].information_schema.columns WHERE table_name = 'tbl1'
Сообщ. #905566
11.10.2006 14:53


Supreme Being

Supreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme Being

модератор
Last Login: 29.10.2007 14:45
Сообщ.: 1 833, Visits: 16 863
Да вы, батенька, извращенец))

а) Ваш запрос лучше будет выглядеть так: UPDATE tbl1 SET Ivan=57 WHERE DateT='09.02.2006'

б) Используйте динамический SQL. Как - читайте BOL. Потрудитесь хоть что-то сами найти.

Сообщ. #905568
11.10.2006 14:56


Supreme Being

Supreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme Being

участник
Last Login: 20.02.2009 9:10
Сообщ.: 275, Visits: 867
:) Что есть - то есть

Если б я еще понимал что искать в BOL
Сообщ. #905570
11.10.2006 14:58
Supreme Being

Supreme Being

модератор
Last Login: 04.05.2008 13:32
Сообщ.: 7 234, Visits: 65 445
По моему только через динамический SQL такое решается. Формируем строку и выполняем ее через sp_executesql.
Сообщ. #905572
11.10.2006 15:15


Supreme Being

Supreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme Being

участник
Last Login: 20.02.2009 9:10
Сообщ.: 275, Visits: 867
А! Понятно! Т.е. вот так:

set @sqlstr='Update tbl1 set '+@name+'='+@cnt+' Where dateT=09.19.2006'
exec(@sqlstr)
Сообщ. #905579
11.10.2006 15:35


Supreme Being

Supreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme BeingSupreme Being

модератор
Last Login: 29.10.2007 14:45
Сообщ.: 1 833, Visits: 16 863
ага... только перед этим сделайте PRINT строки и посомтрите что у вас получилось.
Сообщ. #905581
« пред. тема | след. тема »

12»»

Эту тему читают Expand / Collapse
Посетители: 0 (0 гостей, 0 участников, 0 скрыт.участников)
Сейчас нет участников, просматривающих тему.

Время GMT +3:00, Сейчас 10:19