Модераторы: Akina
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> SQL Энергоучет, помогите неученому в SQL 
:(
    Опции темы
Aleksandr8111
Дата 13.1.2012, 15:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 13.1.2012

Репутация: нет
Всего: нет



Уважаемые специалисты,
помогите, пожалуйста, неученому в SQL'е советами.
 
Задача из области систем по энергоучету (см. структуру в приложенном файле):
в структурной схеме есть элементы обведенные ? знаком - то в чем я, простите, не разбираюсь, но делать надо. 
 
упрощенная структура данных показана в таблице "сводная таблица данных":
В данной таблице показана минимально выборка (почасовка) на период времени с 12:00:00 до 13:00:00. говоря Вашим языком, такая таблица совсем не нормализированная. 

После нормализации (не знаю насколько корректной) получилось 4 таблицы:
R_Energy, R_LEVEL, R_ZONE, R_LOG 
таблица R_LOG имеет "отношения" к таблицам R_Energy и R_ZONE через ключи ID_Energy и ID_ZONE.
 
Далее пытаюсь соорудить перечень SQL запросов к такой "супер БД", по которым была бы возможность суммировать значения величин энергии в зависимости от выборки (почасовка, посуточно) и выводить результаты в отфильтрованном виде (по зонам (SPA, ресторан) и типу энергии (Электрика, Вода, Газ, Тепло)). 
Пытаюсь соорудить SQL запросы в виде функции с некоторыми формальными параметрами:
Код

ALTER PROCEDURE [dbo].[DoRep] 
@ID_Energy int, /* ключ вида Энергии */
@ID_ZONE int, /* ключ вида зоны. если -1, то все зоны */
@DateFirst date, /* начальная дата */
@DateLast date, /* конечная дата */
@TimeFirst time(7), /* начальное время */ 
@TimeLast time(7), /* конечное время */
@Sample int /* выборка. 0 - почасовка, 1 посуточно */
Если данную процедуру вызвать, например, в следующем виде
exec DoRep 1000,-1, '2012-01-10', '2012-01-11', '00:00:00','11:00:00', 0
то результат будет в виде сумм почасовки по электрике по всем зонам за фиксированный период времени. 
На рисунке показан только некоторый фрагмент - по дате 2012-01-10 (таблица "результат запроса")
 
Реализации такой функции видимо очень не оптимальна - в своем теле она вызывает еще несколько функций. 
 
Например, 
реализация SQL запроса вывода отчета для посуточной выборки с фильтром по зонам:
 
Запрос 1 
Код

.. 
SELECT 
R_LOG._Date as "Дата", 
R_Energy.Energy_DESCR as "Энергия",
R_ZONE.ZONE_DESCR as "Зона",
SUM(R_LOG.Value) as "Сумма",
R_Energy.Unit as "Ед.Изм"
 
FROM R_LOG, R_Energy, R_ZONE
WHERE R_LOG.ID_Energy = @ID_Energy AND /* фильтр тип энергии */
R_LOG.ID_ZONE = @ID_ZONE AND /* фильтр зона */
R_LOG.ID_Energy = R_Energy.ID_Energy AND /* выводим по ключу описания типа энергии */
R_LOG.ID_ZONE = R_ZONE.ID_ZONE AND /* выводим по ключу описания зоны */ 
(
R_LOG._Date 
BETWEEN 
@DateFirst AND @DateLast /* промежуток даты */

GROUP BY R_LOG._Date, R_Energy.Energy_DESCR, R_ZONE.ZONE_DESCR, R_Energy.Unit

реализация SQL запроса вывода отчета для посутоной выборки беp фильтра по зонам:
 
Запрос 2
...
Код

SELECT 
R_LOG._Date as "Дата", 
R_Energy.Energy_DESCR as "Энергия",
SUM(R_LOG.Value) as "Сумма",
R_Energy.Unit as "Ед.Изм"
 
FROM R_LOG, R_Energy, R_ZONE
WHERE R_LOG.ID_Energy = @ID_Energy AND /* фильтр тип энергии: электрика */
R_LOG.ID_Energy = R_Energy.ID_Energy AND /* выводим по ключу описания типа энергии */
(
R_LOG._Date 
BETWEEN 
@DateFirst AND @DateLast /* промежуток даты */

GROUP BY R_LOG._Date, R_Energy.Energy_DESCR, R_Energy.Unit
 
Оба запроса реализованы каждый в отдельной функции, которые вызываются в основной процедуре DoRep.  
Данный способ очевидно очень неоптимальный - наверное существуют варианты совмещения двух запросов в одну более сложно обвязанную логикой процедуру, но только у меня совсем не получается это сделать: в первом запросе иимет место ....SELECT  R_ZONE.ZONE_DESCR ..... Во втором запросе зона не рассматривается нигде, так как иначе будет неверно суммироваться значения энергии Value. Таких неоптимальных ситуаций получилось предостаточно - знаний не хватает. 
 
В общем вопросы к Вам весьма примитивны - не судите строго:
1. Насколько удачно спланирована база?
2. Как оптималнее всего построить запросы к базе, так, что бы в конечном счете получилась одна параметризированная функция. Или может такой способ вообще не правильный ? 
 
Всем большое спасибо!

Это сообщение отредактировал(а) Akina - 13.1.2012, 16:57

Присоединённый файл ( Кол-во скачиваний: 14 )
Присоединённый файл  struct.GIF 34,74 Kb
PM MAIL   Вверх
Zloxa
Дата 13.1.2012, 16:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 10
Всего: 161



Цитата(Aleksandr8111 @  13.1.2012,  15:10 Найти цитируемый пост)
После нормализации (не знаю насколько корректной) получилось 4 таблицы:

скажите, а зачем вообще была проведена нормализация?

Цитата(Aleksandr8111 @  13.1.2012,  15:10 Найти цитируемый пост)
 Как оптималнее всего построить запросы к базе,

1) Прежде всего не стоит стремиться к гибкости и универсальности.
Стоит помнить что для каждого запроса строится только один план и самый универсальный запрос, наверняка, будет далеко оптимальным. Совершенно нет ничего зазорного в том, чтобы для каждого способа группировки и для каждого способа фильтрации был реализован специфический запрос, даже в случае, если структура результата одинакова. 
2) Индексируйте те поля, по которым производите фильтрацию. Держите в уме, что запрос может использовать составные индексы, содержащие для них избыточное перечисление столбцов лишь в том случае, если используемые в запросе предикаты производят отбор по первым перечисленным в индексе полям.
Например:
Первому запросу определенно понравится составной индекс по R_LOG(ID_ZONE,ID_Energy,_Date)
Однако же второй запрос не сможет использовать этот индекс.
Если мы индекс перестроим по полям R_LOG(_Date,ID_ZONE,ID_Energy), то второй запрос уже сможет использвать этот индекс, но только лишь для фильтра по дате.
Если же построить индекс по R_LOG(_Date,ID_Energy,ID_ZONE), то оба запроса смогут его использовать и первый, для отбора по всем трем полям и второй для отбора лишь по первым двум.


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
Aleksandr8111
Дата 13.1.2012, 18:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 13.1.2012

Репутация: нет
Всего: нет



Цитата

скажите, а зачем вообще была проведена нормализация?


Не знаю...но так ведь книжка пишет. Если имеет место избыточность, то нормализация нужна, что бы сущности типа "Электрика", "SPA", и т.д. были объявлены  только один раз. Да и в R_LOG сохранять число 1000 (два байта) рациональнее чем слово из девати чаров (девяти байт) "Электрика". В общем я ж не спец, но во всех методиках просто заставляют приводить таблицы к 1NF, 2NF, 3NF и т.д.



Цитата

самый универсальный запрос, наверняка, будет далеко оптимальным


Вы хотели сказать не оптимальным ?
PM MAIL   Вверх
Zloxa
Дата 13.1.2012, 19:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 10
Всего: 161



Цитата(Aleksandr8111 @  13.1.2012,  18:46 Найти цитируемый пост)
но во всех методиках просто заставляют приводить таблицы к 1NF, 2NF, 3NF и т.д.

1) Исходная таблица представлена в 1НФ, если я не ошибаюсь
2) Чтобы прямтаки заставляли - не припомню.  smile 
3) В этих же методиках, обычно пишут, что нормализация в значительной мере усложняет построение аналитических запросов, недоумеваю, почему читающие не доходят до этого места при чтении методик  smile 

Цитата(Aleksandr8111 @  13.1.2012,  18:46 Найти цитируемый пост)
 Да и в R_LOG сохранять число 1000 (два байта) рациональнее чем слово из девати чаров (девяти байт) "Электрика".

Так то можно было слово "Электрика" сократить до "Э", был бы один байт. smile 

И таки зачем?

Обычно нормализация используется для облегчения обеспечения согласованности и целостности данных. В вашем случае, я так понимаю, вы получаете исходные данные откуда то извне - нет? Вероятнее всего на той стороне обеспечен некий комплекс мер, чтобы значение "Электроника" не могло быть представлено как "ЭЛЕКТРОНИКА" или "Электр." -  тот самый случай, для не допущения которого нормализация могла бы быть полезной. А так, получается, вы нормализуете исходные данные, лишь чтобы потом их обратно денормализовать?



--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
Aleksandr8111
Дата 17.1.2012, 13:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 13.1.2012

Репутация: нет
Всего: нет



И все таки, сильного из любопытства ради.
возможно ли в одном запросе объеденить всякую там логику, например
первый вариант запроса

Код

SELECT  
R_LOG._Date,        
R_Energy.Energy_DESCR,
R_ZONE.ZONE_DESCR,    /*!*/
R_Energy.Unit
         
FROM    
R_LOG, 
R_Energy, 
R_ZONE  /*!*/


GROUP BY 
R_LOG._Date,  
R_Energy.Energy_DESCR,                            
R_ZONE.ZONE_DESCR, /*!*/                                    
R_Energy.Unit 


Если строки, отмеченные /*!*/ закоментировать ( /*R_ZONE.ZONE_DESCR*/, /*R_ZONE*/, /*R_ZONE.ZONE_DESCR*/), то получится второй вариант запроса, который можно сохранить в отдельный файл и использовать, но хотелось бы у Вас спросить,  а можно ли два запроса объеденить в один, через какую то логику - может какие то дополнительные операторы SQL. 
Пока все что у меня вышло - это реализовать два запроса в отдельные процедуры (в одной - целый запрос, в другой с закоментированными /*!*/ или поудалять их вообще) 
и вызывать эти два запроса из третей процедуры через IF, ELSE. 


Спасибо.
PM MAIL   Вверх
Zloxa
Дата 17.1.2012, 14:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 10
Всего: 161



Чем вас не устраивает предложенное вами же решение?


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "MS SQL"
Akina

Akina

Запрещается!

Публиковать ссылки и обсуждать взлом чего бы то ни было.

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы составления неспецифических запросов рассматриваются здесь
  • Используйте теги [code=sql][/code] для подсветки кода. Используйтe чекбокс "транслит" (возле кнопок кодов) если у Вас нет русских шрифтов.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Zloxa, Akina.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | MS SQL Server | Следующая тема »


 




[ Время генерации скрипта: 0.1137 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.