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

Откуда:
Сообщений: 2029
Здравствуйте!

Есть поле ТипСвязиТТ и имеет 4 значения:
0 - Это по всему юр лицу
1 - Это по первому признаку объединения ТТ
2 - Это по второму признаку объединения ТТ
3 - Это по непосресдственной одной ТТ

Есть первая таблица. Список мероприятии с участвующими SKU
КодМероприятияЮрЛицоТипСвязиТТКодТТНачалоМероприятияКонецМероприятияSKU
00100111002.01.201803.01.2018SKU1
00200111101_00103.01.201804.01.2018SKU2
00300111202_00204.01.201805.01.2018SKU3
0040011130000405.01.201806.01.2018SKU4
0040011130000405.01.201806.01.2018SKU1

В одном мероприятии могут участвовать больше одной SKU, но периоды одинаковые. См. строки с кодами мероприятии 004.


Есть вторая таблица. Список ТТ
КодТТ ЮрЛицоПервыйПризнакОбъединенияВторойПризнакОбъединения
000010011101_00102_001
000020011101_00102_002
000030011101_00202_003
000040011101_00202_002


+ Нужно получить такую таблицу
КодМероприятияЮрЛицоКодТТSKUДатаМероприятия
0010011100001SKU102.01.2018
0010011100001SKU103.01.2018
0010011100002SKU102.01.2018
0010011100002SKU103.01.2018
0010011100003SKU102.01.2018
0010011100003SKU103.01.2018
0010011100004SKU102.01.2018
0010011100004SKU103.01.2018
0020011100001SKU203.01.2018
0020011100001SKU204.01.2018
0020011100002SKU203.01.2018
0020011100002SKU204.01.2018
0030011100002SKU304.01.2018
0030011100002SKU305.01.2018
0030011100004SKU304.01.2018
0030011100004SKU305.01.2018
0040011100004SKU405.01.2018
0040011100004SKU406.01.2018
0040011100004SKU105.01.2018
0040011100004SKU106.01.2018
Соединение делается таким образом, чтобы получилась таблица со следующими полями: Мероприятие+ЮрЛицо+КодТТ(который попадает через тип связи)+SKU (который участвует в мероприятии)+День (который попадает в период мероприятия).

Начал писать запрос и запутался.

1. Насколько я правильно понимаю, что на первом этапе создаем первую промежуточную таблицу: по каждому мероприятию создаем строки SKU+Дата. На втором этапе создаем вторую промежуточную таблицу: по каждому мероприятию создаются строки непосредственно участвующие ТТ, отобранные с помощью типов связи. На третьем этапе - Соединяем первую и вторую промежуточную таблицу. Для данной задачи по такому алгоритму нужно решать?

2. Для первого этапа пытаюсь использовать такую идею. Что то не получается. Как правильно написать запрос?

+ SQL-Запрос с исходными данными
declare @СписокМероприятий table
(КодМероприятия varchar (3),
	ЮрЛицо varchar (5),
	ТипСвязи integer,
	КодТТ varchar (8),
	НачалоМероприятия date,
	КонецМероприятия date,
	SKU varchar(4))

insert into @СписокМероприятий select '001', '00111',0,null,'02.01.2018', '03.01.2018', 'SKU1'
insert into @СписокМероприятий select '002', '00111',1,'01_001','03.01.2018', '04.01.2018', 'SKU2'
insert into @СписокМероприятий select '003', '00111',2,'02_002','04.01.2018', '05.01.2018', 'SKU3'
insert into @СписокМероприятий select '004', '00111',3,'00004','05.01.2018', '06.01.2018', 'SKU4'
insert into @СписокМероприятий select '004', '00111',3,'00004','05.01.2018', '06.01.2018', 'SKU1'

/*Select * FROM @СписокМероприятий*/



declare @СписокТТ table
(КодТТ varchar (5),
	ЮрЛицо varchar (5),
	ПервыйПризнакОбъединения varchar (6),
	ВторойПризнакОбъединения varchar (6))

insert into @СписокТТ select '00001', '00111','01_001','02_001'
insert into @СписокТТ select '00002', '00111','01_001','02_002'
insert into @СписокТТ select '00003', '00111','01_002','02_003'
insert into @СписокТТ select '00004', '00111','01_002','02_002'


/*Select * FROM @СписокТТ*/


declare @ПромежуточнаяТаблицаДаты table (Дата date)
declare @ПромежуточнаяДата datetime = '01.01.2018'

while @ПромежуточнаяДата <= '10.01.2018'
begin
insert @ПромежуточнаяТаблицаДаты (Дата) select @ПромежуточнаяДата
set @ПромежуточнаяДата = dateadd(dd,1,@ПромежуточнаяДата)
end

/*select * from @ПромежуточнаяТаблицаДаты*/

select
	КодМероприятия,
	ЮрЛицо,
	SKU
FROM
	@СписокМероприятий
outer apply
	(Select 
		Дата
	FROM
		@ПромежуточнаяТаблицаДаты
	where
		ПромежуточнаяТаблицаДаты.Дата >= СписокМероприятий.НачалоМероприятия 
		AND
		ПромежуточнаяТаблицаДаты.Дата <= СписокМероприятий.КонецМероприятия) AS Таблица


Если писать так
	where
		@ПромежуточнаяТаблицаДаты.Дата >= @СписокМероприятий.НачалоМероприятия 
		AND
		@ПромежуточнаяТаблицаДаты.Дата <= @СписокМероприятий.КонецМероприятия) AS Таблица
то пишет что нужно объявить скалярные переменные. А если убрать знак @, то пишет, что не удалось привязать составной идентификатор.

Почему так?

И возможно ли обойтись без @ПромежуточнаяТаблицаДаты? Все таки изначально не знаем какие начальные и конечные даты должны быть в этой таблице.
11 янв 18, 13:48    [21097120]     Ответить | Цитировать Сообщить модератору
 Re: Вопрос по SQL-запросу  [new]
Akina
Member

Откуда: Зеленоград, Москва, Россия
Сообщений: 20189
По-моему, во второй таблице упущено поле SKU... без него не очень срастается.
11 янв 18, 14:29    [21097372]     Ответить | Цитировать Сообщить модератору
 Re: Вопрос по SQL-запросу  [new]
Руслан Дамирович
Member

Откуда: Резиновая нерезиновая
Сообщений: 940
+ Просьба убрать от мониторов кошек и детей, беременных и кормящих женщин, и других психически нестабильных личностей
DECLARE @СписокМероприятий TABLE
(КодМероприятия varchar (3),
	ЮрЛицо varchar (5),
	ТипСвязи integer,
	КодТТ varchar (8),
	НачалоМероприятия date,
	КонецМероприятия date,
	SKU varchar(4))
;
INSERT INTO
  @СписокМероприятий
VALUES 
  ( '001', '00111', 0,     NULL, '20180102', '20180103', 'SKU1' ),
  ( '002', '00111', 1, '01_001', '20180103', '20180104', 'SKU2' ),
  ( '003', '00111', 2, '02_002', '20180104', '20180105', 'SKU3' ),
  ( '004', '00111', 3,  '00004', '20180105', '20180106', 'SKU4' ),
  ( '004', '00111', 3,  '00004', '20180105', '20180106', 'SKU1' )
;
DECLARE @СписокТТ TABLE
(КодТТ varchar (5),
	ЮрЛицо varchar (5),
	ПервыйПризнакОбъединения varchar (6),
	ВторойПризнакОбъединения varchar (6))
;
INSERT INTO
  @СписокТТ 
VALUES 
  ( '00001', '00111', '01_001', '02_001' ),
  ( '00002', '00111', '01_001', '02_002' ),
  ( '00003', '00111', '01_002', '02_003' ),
  ( '00004', '00111', '01_002', '02_002' )
;
WITH
t AS (
  SELECT
    mm.[КодМероприятия],
    tt.[ЮрЛицо],
    tt.[КодТТ],
    mm.[SKU],
    [Дата] = mm.[НачалоМероприятия],
    mm.[КонецМероприятия]
  FROM
    @СписокМероприятий mm
    INNER JOIN @СписокТТ tt ON (
          1 = CASE
            WHEN mm.[ТипСвязи] = 0 AND tt.[ЮрЛицо] = mm.[ЮрЛицо] THEN 1
            WHEN mm.[ТипСвязи] = 1 AND tt.[ЮрЛицо] = mm.[ЮрЛицо] AND tt.[ПервыйПризнакОбъединения] = mm.[КодТТ] THEN 1
            WHEN mm.[ТипСвязи] = 2 AND tt.[ЮрЛицо] = mm.[ЮрЛицо] AND tt.[ВторойПризнакОбъединения] = mm.[КодТТ] THEN 1
            WHEN mm.[ТипСвязи] = 3 AND tt.[ЮрЛицо] = mm.[ЮрЛицо] AND tt.[КодТТ] = mm.[КодТТ] THEN 1
          END )
  UNION ALL
  SELECT
    t.[КодМероприятия],
    t.[ЮрЛицо],
    t.[КодТТ],
    t.[SKU],
    [Дата] = DATEADD( DAY, 1, t.[Дата] ),
    t.[КонецМероприятия]
  FROM
    t
  WHERE
    t.[Дата] < t.[КонецМероприятия]
)
SELECT
  [КодМероприятия],
  [ЮрЛицо],
  [КодТТ],
  [SKU],
  [Дата]
FROM
  t
ORDER BY
  1, 2, 3, 4, 5
OPTION (
  MAXRECURSION 0 )
11 янв 18, 14:51    [21097619]     Ответить | Цитировать Сообщить модератору
 Re: Вопрос по SQL-запросу  [new]
ferzmikk
Member

Откуда:
Сообщений: 2029
Akina
По-моему, во второй таблице упущено поле SKU... без него не очень срастается.

Вторая таблица отображает список ТТ и не имеет связи с SKU. Таблица отображает какая именно ТТ относится в группе для первого признака и в какой группе для второго признака, и какое юридическое лицо. Потом с помощью поля "Тип связи" и "Код ТТ" из первой таблицы вытаскиваются коды ТТ. Поле "Код ТТ" из первой таблицы, это не только код ТТ, но и Коды полей "ПервыйПризнакОбъединения" "ВторойПризнакОбъединения".
11 янв 18, 14:59    [21097693]     Ответить | Цитировать Сообщить модератору
 Re: Вопрос по SQL-запросу  [new]
Akina
Member

Откуда: Зеленоград, Москва, Россия
Сообщений: 20189
Руслан Дамирович, я бы условие tt.[ЮрЛицо] = mm.[ЮрЛицо] в секции ON вынес за пределы CASE...
11 янв 18, 16:35    [21098276]     Ответить | Цитировать Сообщить модератору
 Re: Вопрос по SQL-запросу  [new]
Руслан Дамирович
Member

Откуда: Резиновая нерезиновая
Сообщений: 940
Akina
Руслан Дамирович, я бы условие tt.[ЮрЛицо] = mm.[ЮрЛицо] в секции ON вынес за пределы CASE...

Когда будем оптимизировать - несомненно.
Но в общем случае и в отсутствие информации об индексах - возле птиц.
11 янв 18, 18:30    [21098716]     Ответить | Цитировать Сообщить модератору
 Re: Вопрос по SQL-запросу  [new]
ferzmikk
Member

Откуда:
Сообщений: 2029
Руслан Дамирович,

Спасибо, разбираю!
11 янв 18, 20:07    [21098915]     Ответить | Цитировать Сообщить модератору
 Re: Вопрос по SQL-запросу  [new]
ferzmikk
Member

Откуда:
Сообщений: 2029
ferzmikk
Если писать так
	where
		@ПромежуточнаяТаблицаДаты.Дата >= @СписокМероприятий.НачалоМероприятия 
		AND
		@ПромежуточнаяТаблицаДаты.Дата <= @СписокМероприятий.КонецМероприятия) AS Таблица
то пишет что нужно объявить скалярные переменные. А если убрать знак @, то пишет, что не удалось привязать составной идентификатор.

Почему так?

Это бы понять еще
11 янв 18, 20:09    [21098919]     Ответить | Цитировать Сообщить модератору
 Re: Вопрос по SQL-запросу  [new]
ferzmikk
Member

Откуда:
Сообщений: 2029
Руслан Дамирович
Akina
Руслан Дамирович, я бы условие tt.[ЮрЛицо] = mm.[ЮрЛицо] в секции ON вынес за пределы CASE...

Когда будем оптимизировать - несомненно.
Но в общем случае и в отсутствие информации об индексах - возле птиц.
А куда вынести за пределы CASE? В WHERE затолкать?
11 янв 18, 20:53    [21099007]     Ответить | Цитировать Сообщить модератору
 Re: Вопрос по SQL-запросу  [new]
ferzmikk
Member

Откуда:
Сообщений: 2029
Руслан Дамирович,

+
...
WITH
t AS (
  SELECT
    mm.[КодМероприятия],
    tt.[ЮрЛицо],
    tt.[КодТТ],
    mm.[SKU],
    [Дата] = mm.[НачалоМероприятия],
    mm.[КонецМероприятия]
  FROM
    ...
  UNION ALL
  SELECT
    t.[КодМероприятия],
    t.[ЮрЛицо],
    t.[КодТТ],
    t.[SKU],
    [Дата] = DATEADD( DAY, 1, t.[Дата] ),
    t.[КонецМероприятия]
  FROM
    t
  WHERE
    t.[Дата] < t.[КонецМероприятия]
)
...

Получается [Дата] до UNION ALL присваивается один раз. Дальше начинается цикл: [Дата] из функции DATEADD и WHERE берется из последнего [Дата], и далее присваивается новое [Дата] после UNION ALL SELECT. Аналогично по следующей итерации. Верно понимаю?
11 янв 18, 21:11    [21099054]     Ответить | Цитировать Сообщить модератору
 Re: Вопрос по SQL-запросу  [new]
Руслан Дамирович
Member

Откуда: Резиновая нерезиновая
Сообщений: 940
Да, обычное такое CTE с иерархией
12 янв 18, 09:01    [21099770]     Ответить | Цитировать Сообщить модератору
 Re: Вопрос по SQL-запросу  [new]
iap
Member

Откуда: Москва
Сообщений: 46952
ferzmikk
ferzmikk
Если писать так
	where
		@ПромежуточнаяТаблицаДаты.Дата >= @СписокМероприятий.НачалоМероприятия 
		AND
		@ПромежуточнаяТаблицаДаты.Дата <= @СписокМероприятий.КонецМероприятия) AS Таблица

то пишет что нужно объявить скалярные переменные. А если убрать знак @, то пишет, что не удалось привязать составной идентификатор.

Почему так?

Это бы понять еще
[@ПромежуточнаяТаблицаДаты].Дата
Или применять алиасы, что лучше всего
12 янв 18, 09:12    [21099794]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить