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

Откуда: Казахстан, Петропавловск
Сообщений: 302
Задача заключается в следующем, у каждого абонента есть свой набор программ (ТВ каналов - для ясности), абонент может в течении месяца менять данный набор программ, в начале следующего месяца выбранный набор программ должен вступить в силу. Т.е. по сути нужно разделить текущий период и следующий.
Была создана таблица, в которой есть поля такие как Abonent_id -номер абонента, Program_id -номер программы, NextPeriod - флаг, говорящий о том что данная программа запланирована на следующий период-месяц.

Пример следующий:

declare @t table (Abonent_id int, Program_id int, NextPeriod int)
INSERT INTO @t VALUES(0,1,0)
INSERT INTO @t VALUES(0,2,0)
INSERT INTO @t VALUES(0,7,0)
INSERT INTO @t VALUES(0,11,0)
INSERT INTO @t VALUES(0,128,0)
INSERT INTO @t VALUES(0,8,1)
INSERT INTO @t VALUES(0,15,1)
INSERT INTO @t VALUES(0,16,1)
INSERT INTO @t VALUES(0,17,1)

SELECT * FROM @t

delete from @t where (NextPeriod=0) and ((select max(NextPeriod) from @t) > 0)

SELECT * FROM @t 

Нужно удалить все строки у абонентов и у которых NextPeriod=0, но при условии, что у каждого из них есть запланированные программы, т.е. NextPeriod=1

Я нацарапал запрос на удаление, вроде работает, но чувствую что это такая лажа, покритикуйте пожалуйста насчет самого принципа хранения таких данных и удаления не нужных строк.
28 авг 11, 01:21    [11191214]     Ответить | Цитировать Сообщить модератору
 Re: Покритикуйте мой подход  [new]
locky
Member

Откуда: Харьков, Украина
Сообщений: 62034
хорошим подспорьем при написании запроса является четкое формулирование задачи на обычном русском языке с дальнейшим простым переводом на "язык" запросов.

зы а запрос у вас - неправильный.
28 авг 11, 01:39    [11191232]     Ответить | Цитировать Сообщить модератору
 Re: Покритикуйте мой подход  [new]
SamMan
Member

Откуда: Moscow
Сообщений: 759
А еще большим подспорьем является буквальное следование ВСЕМ пунктам из Рекомендации по оформлению сообщений в форуме.
Покамест у вас удаляются все строки с NextPeriod=0 при условии наличия хотя бы одной строки NextPeriod=1. Если это то что требуется - поздравляю.
28 авг 11, 12:57    [11191549]     Ответить | Цитировать Сообщить модератору
 Re: Покритикуйте мой подход  [new]
Константин Цветков
Member

Откуда: Москва
Сообщений: 1735
Crvik
Нужно удалить все строки у абонентов и у которых NextPeriod=0, но при условии, что у каждого из них есть запланированные программы, т.е. NextPeriod=1
Почему? Если пользователь запланировал изменения, а потом их все отменил, его чистить не надо?
28 авг 11, 13:33    [11191612]     Ответить | Цитировать Сообщить модератору
 Re: Покритикуйте мой подход  [new]
Crvik
Member

Откуда: Казахстан, Петропавловск
Сообщений: 302
locky
хорошим подспорьем при написании запроса является четкое формулирование задачи на обычном русском языке с дальнейшим простым переводом на "язык" запросов.

зы а запрос у вас - неправильный.


Я плохо сформулировал свою задачу? Вроде все понятно написал, если есть какие то вопросы по задаче то спросите я с удовольствием отвечу. А то что запрос не верный я написал, я сразу же признался, что смог сообразить то и написал, как говорится самое главное начать. Решил у специалистов попросить рекомендации, как лучше сделать. А натолкнулся лишь только на оффтоп, очень жаль :(
28 авг 11, 15:39    [11191814]     Ответить | Цитировать Сообщить модератору
 Re: Покритикуйте мой подход  [new]
Crvik
Member

Откуда: Казахстан, Петропавловск
Сообщений: 302
Константин Цветков
Crvik
Нужно удалить все строки у абонентов и у которых NextPeriod=0, но при условии, что у каждого из них есть запланированные программы, т.е. NextPeriod=1
Почему? Если пользователь запланировал изменения, а потом их все отменил, его чистить не надо?


Если пользователь отменил запланированные изменения, то в этот момент можно просто почистить все с NextPeriod=1, после чего в начале следующего месяца хранимая процедура не увидит, что запланировано что то на этот месяц и небудет ничего делать по данному абоненту..
28 авг 11, 15:43    [11191818]     Ответить | Цитировать Сообщить модератору
 Re: Покритикуйте мой подход  [new]
ё
Guest
Crvik
locky
хорошим подспорьем при написании запроса является четкое формулирование задачи на обычном русском языке с дальнейшим простым переводом на "язык" запросов.

зы а запрос у вас - неправильный.


Я плохо сформулировал свою задачу? Вроде все понятно написал, если есть какие то вопросы по задаче то спросите я с удовольствием отвечу. А то что запрос не верный я написал, я сразу же признался, что смог сообразить то и написал, как говорится самое главное начать. Решил у специалистов попросить рекомендации, как лучше сделать. А натолкнулся лишь только на оффтоп, очень жаль :(


нуу, эту фразу
Crvik
Нужно удалить все строки у абонентов и у которых NextPeriod=0, но при условии, что у каждого из них есть запланированные программы, т.е. NextPeriod=1

можно действительно понять как угодно ...

и про "Рекомендации по оформлению сообщений" вам не зря напоминают,
вполне, возможно, - достаточно было бы показать желаемый результат, что бы не заставлять никого гадать ...

-------------------
это ?
delete t1
from @t t1 
where (NextPeriod=0) 
  and exists (select 1 from @t t2 where t1.Abonent_id=t2.Abonent_id and t2.NextPeriod=1)
28 авг 11, 15:50    [11191831]     Ответить | Цитировать Сообщить модератору
 Re: Покритикуйте мой подход  [new]
locky
Member

Откуда: Харьков, Украина
Сообщений: 62034
Crvik
locky
хорошим подспорьем при написании запроса является четкое формулирование задачи на обычном русском языке с дальнейшим простым переводом на "язык" запросов.

зы а запрос у вас - неправильный.


Я плохо сформулировал свою задачу? Вроде все понятно написал, если есть какие то вопросы по задаче то спросите я с удовольствием отвечу. А то что запрос не верный я написал, я сразу же признался, что смог сообразить то и написал, как говорится самое главное начать. Решил у специалистов попросить рекомендации, как лучше сделать. А натолкнулся лишь только на оффтоп, очень жаль :(

Я то вашу задачу понял, но вы для себя не сумели её четко сформулировать :(


как я понял, задача формулируется так
УДАЛИТЬ СТРОКИ
ИЗ ТАБЛИЦЫ <ТАБЛИЦА>
ДЛЯ КОТОРЫХ <ПЕРИОД> РАВЕН НУЛЮ И СУЩЕСТВУЕТ ЗАПИСЬ ИЗ ТАБЛИЦЫ <ТАБЛИЦА> В КОТОРОЙ АБОНЕНТ РАВЕН ЭТОМУ ЖЕ АБОНЕНТУ И <ПЕРИОД> БОЛЬШЕ НУЛЯ
?
28 авг 11, 15:51    [11191836]     Ответить | Цитировать Сообщить модератору
 Re: Покритикуйте мой подход  [new]
Crvik
Member

Откуда: Казахстан, Петропавловск
Сообщений: 302
ё
Crvik
пропущено...


Я плохо сформулировал свою задачу? ...


нуу, эту фразу
Crvik
Нужно удалить все строки у абонентов и у которых NextPeriod=0, но при условии, что у каждого из них есть запланированные программы, т.е. NextPeriod=1

можно действительно понять как угодно ...


Да, видать тут я перемудрил, чуток.

ё
и про "Рекомендации по оформлению сообщений" вам не зря напоминают,
вполне, возможно, - достаточно было бы показать желаемый результат, что бы не заставлять никого гадать ...

-------------------
это ?
delete t1
from @t t1 
where (NextPeriod=0) 
  and exists (select 1 from @t t2 where t1.Abonent_id=t2.Abonent_id and t2.NextPeriod=1)


Согласен, нужно было показать что должно получится было бы проще.

Да, этот запрос делает то что нужно. Спасибо!

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

Народ, кто как посоветует хранить такие данные ?
28 авг 11, 16:19    [11191878]     Ответить | Цитировать Сообщить модератору
 Re: Покритикуйте мой подход  [new]
SamMan
Member

Откуда: Moscow
Сообщений: 759
Crvik
Народ, кто как посоветует хранить такие данные ?


Прямо готового решения не скажу, зато подскажу классные слова для последующего гугления: "дизайн баз данных" и "нормализация таблиц". По архитектурным вопросам сложно получить однозначно верный ответ, это вам не скрипт, который если работает - то работает, а если нет - то точно нет.
28 авг 11, 19:01    [11192178]     Ответить | Цитировать Сообщить модератору
 Re: Покритикуйте мой подход  [new]
Edd.Dragon
Member

Откуда: Украина
Сообщений: 6963
Crvik
Нужно удалить все строки у абонентов и у которых NextPeriod=0, но при условии, что у каждого из них есть запланированные программы, т.е. NextPeriod=1

И при этом же NextPeriod оставшихся сменить на 0?

А если завести для следующего месяца отдельную табличку?
Тогда нужно выполнить три запроса:
1. Удалить из первой таблицы записи юзеров, для которых найдутся записи во второй таблице.
2. Вставить все записи из второй в первую.
3. Очистить вторую таблицу.
28 авг 11, 19:23    [11192209]     Ответить | Цитировать Сообщить модератору
 Re: Покритикуйте мой подход  [new]
Crvik
Member

Откуда: Казахстан, Петропавловск
Сообщений: 302
Edd.Dragon
Crvik
Нужно удалить все строки у абонентов и у которых NextPeriod=0, но при условии, что у каждого из них есть запланированные программы, т.е. NextPeriod=1

И при этом же NextPeriod оставшихся сменить на 0?

А если завести для следующего месяца отдельную табличку?
Тогда нужно выполнить три запроса:
1. Удалить из первой таблицы записи юзеров, для которых найдутся записи во второй таблице.
2. Вставить все записи из второй в первую.
3. Очистить вторую таблицу.


Да, именно такой алгоритм я вижу перед собой и описывал в предыдущем посте.
Но вторая табличка будет содержать идентичные поля, мы избавимся только от поля NextPeriod, тем самым в место одного запроса будем выполнять три запроса, что не очень оптимально ИМХО. Только из-за этого я решил хранить все данные в одной табличке, разделяя текущий период и следующий полем NextPeriod.
28 авг 11, 21:59    [11192521]     Ответить | Цитировать Сообщить модератору
 Re: Покритикуйте мой подход  [new]
Edd.Dragon
Member

Откуда: Украина
Сообщений: 6963
Crvik
три запроса, что не очень оптимально ИМХО.

Уверен?

Один запрос с подзапросом может стоить десятков простых запросов. Так что, 3 vs 1 - ни о чем не говорит.
28 авг 11, 22:20    [11192573]     Ответить | Цитировать Сообщить модератору
 Re: Покритикуйте мой подход  [new]
Ural2
Member

Откуда:
Сообщений: 58
Я бы на вашем месте вместо поля NextPeriod сделала поле DateTime.
Преимущества:
1. сохраняется ретроспектива (полезно для "разбора полетов" или отката)
2. ничего удалять не надо (разве что по времени давности)
3. запрос на выборку элементарный:
select Abonent_Id, Program_id, Max(DT)
from Table
group by Abonent_Id, Program_id
29 авг 11, 12:43    [11194355]     Ответить | Цитировать Сообщить модератору
 Re: Покритикуйте мой подход  [new]
Edd.Dragon
Member

Откуда: Украина
Сообщений: 6963
Ural2
Я бы на вашем месте вместо поля NextPeriod сделала поле DateTime.
Преимущества:
1. сохраняется ретроспектива (полезно для "разбора полетов" или отката)
2. ничего удалять не надо (разве что по времени давности)
3. запрос на выборку элементарный:
select Abonent_Id, Program_id, Max(DT)
from Table
group by Abonent_Id, Program_id

Т.е. выберется

Канал1 (сентябрь) ???
Канал2 (август)
Канал5 (апрель) ???
Канал7 (август)

1. Выбирать надо строго за последний из имеющихся месяцев по абоненту. Подзапрос?
2. Абонент сменил свои настройки на сентябрь еще в середине августа. Пол августа по этому абоненту надо выбирать АВГУСТ при наличии сентября. А с сентября уже выбирать последний месяц.
29 авг 11, 12:58    [11194461]     Ответить | Цитировать Сообщить модератору
 Re: Покритикуйте мой подход  [new]
Ural2
Member

Откуда:
Сообщений: 58
Логично. Нужно добавить условие "на какую дату актуально", например, на сегодня:
select Abonent_Id, Program_id, Max(DT)
from Table
group by Abonent_Id, Program_id
where DT<=GetDate()
29 авг 11, 13:03    [11194496]     Ответить | Цитировать Сообщить модератору
 Re: Покритикуйте мой подход  [new]
Edd.Dragon
Member

Откуда: Украина
Сообщений: 6963
Ural2,

select Abonent_Id, Program_id, DT {MAX не нужен}
from Table
group by Abonent_Id, Program_id
where DT = {август}
или
where DT >= {начало_августа} AND DT <= {август}
29 авг 11, 13:16    [11194600]     Ответить | Цитировать Сообщить модератору
 Re: Покритикуйте мой подход  [new]
Edd.Dragon
Member

Откуда: Украина
Сообщений: 6963
А нет. Так мы не выберем тех, кто давно не менял.

А твой вариант выберет лишнее, если менял в апреле и в августе. Выберет такие апрельские программы, которых я не поставил на агуст.
29 авг 11, 13:17    [11194605]     Ответить | Цитировать Сообщить модератору
 Re: Покритикуйте мой подход  [new]
Edd.Dragon
Member

Откуда: Украина
Сообщений: 6963
Т.е. фактически необходимо условие
WHERE месяц = MAX(месяц, но не сентябрь)
29 авг 11, 13:19    [11194620]     Ответить | Цитировать Сообщить модератору
 Re: Покритикуйте мой подход  [new]
Ural2
Member

Откуда:
Сообщений: 58
Как же Max не нужен? В этом вся суть - выберутся по одной максимальной дате для каждого абонента и канала.
29 авг 11, 13:20    [11194628]     Ответить | Цитировать Сообщить модератору
 Re: Покритикуйте мой подход  [new]
Edd.Dragon
Member

Откуда: Украина
Сообщений: 6963
Ural2
Как же Max не нужен? В этом вся суть - выберутся по одной максимальной дате для каждого абонента и канала.

Верно!

Канал2 (август)
Канал5 (апрель)
Канал7 (август)


Пятый не нужно выбирать! Это из моих апрельских настроек. А в августовских пятого нет. Но он был в апреле и выберется таким запросом ))
29 авг 11, 13:24    [11194682]     Ответить | Цитировать Сообщить модератору
 Re: Покритикуйте мой подход  [new]
Crvik
Member

Откуда: Казахстан, Петропавловск
Сообщений: 302
Ural2, спасибо за наводку, предложенный вами вариант я не рассматривал еще.
Вот что у меня получилось:
declare @t table (Abonent_id int, Program_id int, DT DateTime)
INSERT INTO @t VALUES(0,1,'01.01.2011')
INSERT INTO @t VALUES(0,2,'01.01.2011')
INSERT INTO @t VALUES(0,7,'01.01.2011')
INSERT INTO @t VALUES(0,11,'01.01.2011')
INSERT INTO @t VALUES(0,128,'01.01.2011')
INSERT INTO @t VALUES(0,8,'15.05.2011')
INSERT INTO @t VALUES(0,15,'15.05.2011')
INSERT INTO @t VALUES(0,16,'15.05.2011')
INSERT INTO @t VALUES(0,17,'15.05.2011')

SELECT * FROM @t

select Abonent_id, Program_id, DT
from @t
Group by Abonent_id, Program_id, DT
having DT=(Select max(DT) from @t)

Тем самым мы вытащим всех абонентов со свежими каналами.
Такой запрос имеет право жить?
29 авг 11, 14:00    [11194973]     Ответить | Цитировать Сообщить модератору
 Re: Покритикуйте мой подход  [new]
Программист-Любитель
Member

Откуда:
Сообщений: 16839
Схема данных мне не нравится. Такое впечатление, что идет увлекательное путешествие в трех соснах. Есть стандартный паттерн - интервальные во времени данные. Таблицы: Каналов, Абонентов, ВыборКаналовАбонентами (id абонента, id канала, Дата С, Дата По). Если Дата По открытая - то канал должнен попадать в выборку по всем даатм начиная с Дата С. И табличную функцию от даты, показывающую каналы, действующие для данного абонента. Простейшее соединения по BETWEEN. Плюс процедуры: снимающая выбор с канала и выбиращая канал, обе от даты.
29 авг 11, 14:08    [11195017]     Ответить | Цитировать Сообщить модератору
 Re: Покритикуйте мой подход  [new]
Ural2
Member

Откуда:
Сообщений: 58
Crvik
select Abonent_id, Program_id, DT
from @t
Group by Abonent_id, Program_id, DT
having DT=(Select max(DT) from @t)
Тем самым мы вытащим всех абонентов со свежими каналами.
Такой запрос имеет право жить?


Нет, это не правильно, вы выберете данные только по одной максимальной дате для все и вся, а нам нужно найти максимум для каждой пары абонент-канал, ограничив при этом поиск некоторой датой сверху.
Не понимаю чем вам не нравится этот вариант:
select Abonent_id, Program_id, Мах(DT) as DT
from @t
Group by Abonent_id, Program_id
where DT<=@MyDT
29 авг 11, 14:28    [11195147]     Ответить | Цитировать Сообщить модератору
 Re: Покритикуйте мой подход  [new]
Crvik
Member

Откуда: Казахстан, Петропавловск
Сообщений: 302
Ural2
Нет, это не правильно, вы выберете данные только по одной максимальной дате для все и вся, а нам нужно найти максимум для каждой пары абонент-канал, ограничив при этом поиск некоторой датой сверху.


Согласен, не сработает такой запрос для пары абонент-канал.

Ural2
Не понимаю чем вам не нравится этот вариант:
select Abonent_id, Program_id, Мах(DT) as DT
from @t
Group by Abonent_id, Program_id
where DT<=@MyDT


Данный вариант не хочет работать, сервер ругается на синтаксис.
Привел запрос в следующий вид:
declare @t table (Abonent_id int, Program_id int, DT DateTime)
INSERT INTO @t VALUES(0,1,'01.01.2011')
INSERT INTO @t VALUES(0,2,'01.01.2011')
INSERT INTO @t VALUES(0,7,'01.01.2011')
INSERT INTO @t VALUES(0,11,'01.01.2011')
INSERT INTO @t VALUES(0,128,'01.01.2011')
INSERT INTO @t VALUES(0,8,'15.05.2011')
INSERT INTO @t VALUES(0,15,'15.05.2011')
INSERT INTO @t VALUES(0,16,'15.05.2011')
INSERT INTO @t VALUES(0,17,'15.05.2011')


declare @MyDT datetime
set @MyDT='01.06.2011' --текущая дата

select Abonent_id, Program_id, Max(DT) as DT
from @t
Group by Abonent_id, Program_id, DT
having DT<=@MyDT

Это вы хотели сказать?
29 авг 11, 14:44    [11195250]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить