Имя: Пароль:
1C
1С v8
Получить длину объединения
,
0 Ненавижу 1С
 
гуру
28.06.12
11:57
В рамках 1С 8 тренировочная задачка на запросы
Есть таблица Т с двумя числовыми полями А и Б, А<Б всегда
Каждая запись таблицы интерпретируется как отрезок с координами концов А и Б на координатной прямой
Берется объединение всех отрезков таблицы

Требуется найти длину полученного объединения
27 Ненавижу 1С
 
гуру
28.06.12
12:51
(26) я вам что, калькулятор?
объединяем, получаем
1-6
9-20
45-46
5+11+1=17
28 ssh2012
 
28.06.12
12:53
(27) зачем калькулятор, у тебя же готовый запрос есть, подставляй))
29 Cyberhawk
 
28.06.12
12:54
Мне думается, что существует готовач формула для такой задачи и в запросе надо не изобретать велосипед, а воспользоваться ею :)
30 Ненавижу 1С
 
гуру
28.06.12
12:55
(28) дык в неудобном виде он данные дал ))
(29) выдай нам ее
31 Cyberhawk
 
28.06.12
12:56
(30) а последовательность отрезков в исходной таблице произвольная?
32 Ненавижу 1С
 
гуру
28.06.12
12:57
(31) а это на что может повлиять?
работая с таблицами БД надо абстрагироваться от понятия порядок
33 y88
 
28.06.12
13:00
внутреннее соединение, не?
34 Homer
 
28.06.12
13:04
//
ВЫБРАТЬ
   1 КАК Поле1,
   5 КАК Поле2
ПОМЕСТИТЬ мТаб

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   2,
   5

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   3,
   6

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   8,
   10
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   мТаб.Поле1,
   мТаб.Поле2 - мТаб.Поле1 КАК Раз,
   мТаб.Поле2
ПОМЕСТИТЬ мТаб2
ИЗ
   мТаб КАК мТаб
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   мТаб2.Поле1 КАК Поле1,
   мТаб2.Раз КАК Раз,
   мТаб2.Поле2 КАК Поле2
ПОМЕСТИТЬ мДва
ИЗ
   мТаб2 КАК мТаб2
       ВНУТРЕННЕЕ СОЕДИНЕНИЕ мТаб2 КАК мТаб21
       ПО мТаб2.Поле1 >= мТаб21.Поле1
           И мТаб2.Поле2 > мТаб21.Поле2

СГРУППИРОВАТЬ ПО
   мТаб2.Поле1,
   мТаб2.Раз,
   мТаб2.Поле2
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   МИНИМУМ(мТаб2.Поле1) КАК Поле1,
   ВложенныйЗапрос.Поле1 КАК Поле11
ПОМЕСТИТЬ мОдин
ИЗ
   мТаб2 КАК мТаб2,
   (ВЫБРАТЬ ПЕРВЫЕ 1
       мДва.Поле1 КАК Поле1
   ИЗ
       мДва КАК мДва) КАК ВложенныйЗапрос

СГРУППИРОВАТЬ ПО
   ВложенныйЗапрос.Поле1
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   мрез2.Поле1,
   мрез2.Раз КАК Раз,
   мрез2.Поле2
ИЗ
   (ВЫБРАТЬ
       мОдин.Поле1 КАК Поле1,
       мОдин.Поле11 - мОдин.Поле1 КАК Раз,
       мОдин.Поле11 КАК Поле2
   ИЗ
       мОдин КАК мОдин
   
   ОБЪЕДИНИТЬ ВСЕ
   
   ВЫБРАТЬ
       мДва.Поле1,
       мДва.Раз,
       мДва.Поле2
   ИЗ
       мДва КАК мДва) КАК мрез2
ИТОГИ
   СУММА(Раз)
ПО
   ОБЩИЕ
35 Homer
 
28.06.12
13:09
(34)пример не удачный, не работает
36 PuhUfa
 
28.06.12
13:11
Создаем Таблицу (ТаблицаКоординат) количеством столбцов макс(Б)
Заполняем ее данными из исходной таблицы по принципу:
1 строка исходной Т -> 1 строка ТаблицыКоординат
в столбцы ТаблицыКоординат пишем 0 или 1 в зависимости от того попадает номер этого столбца в отрезок А-Б
Пример:
Исходня Т
А = 2 Б = 5
А = 3 Б = 4
ТаблицаКоординат:
0|1|1|1|1
0|0|1|1|0

ТаблицаКоординат сворачиваем, считаем количество столбцов где значение не равно 0.

ps во блин загнул -)
37 Homer
 
28.06.12
13:12
ВЫБРАТЬ
   1 КАК Поле1,
   5 КАК Поле2
ПОМЕСТИТЬ мТаб

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   2,
   5

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   3,
   6

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   8,
   10
   ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   8,
   14

;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   мТаб.Поле1,
   мТаб.Поле2 - мТаб.Поле1 КАК Раз,
   мТаб.Поле2
ПОМЕСТИТЬ мТаб2
ИЗ
   мТаб КАК мТаб
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   мТаб2.Поле1 КАК Поле1,
   мТаб2.Раз КАК Раз,
   мТаб2.Поле2 КАК Поле2
ПОМЕСТИТЬ мДва
ИЗ
   мТаб2 КАК мТаб2
       ВНУТРЕННЕЕ СОЕДИНЕНИЕ мТаб2 КАК мТаб21
       ПО мТаб2.Поле1 >= мТаб21.Поле1
           И мТаб2.Поле2 > мТаб21.Поле2
           И мТаб2.Поле1 < мТаб21.Поле2


СГРУППИРОВАТЬ ПО
   мТаб2.Поле1,
   мТаб2.Раз,
   мТаб2.Поле2
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   МИНИМУМ(мТаб2.Поле1) КАК Поле1,
   ВложенныйЗапрос.Поле1 КАК Поле11
ПОМЕСТИТЬ мОдин
ИЗ
   мТаб2 КАК мТаб2,
   (ВЫБРАТЬ ПЕРВЫЕ 1
       мДва.Поле1 КАК Поле1
   ИЗ
       мДва КАК мДва) КАК ВложенныйЗапрос

СГРУППИРОВАТЬ ПО
   ВложенныйЗапрос.Поле1
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   мрез2.Поле1,
   мрез2.Раз КАК Раз,
   мрез2.Поле2
ИЗ
   (ВЫБРАТЬ
       мОдин.Поле1 КАК Поле1,
       мОдин.Поле11 - мОдин.Поле1 КАК Раз,
       мОдин.Поле11 КАК Поле2
   ИЗ
       мОдин КАК мОдин
   
   ОБЪЕДИНИТЬ ВСЕ
   
   ВЫБРАТЬ
       мДва.Поле1,
       мДва.Раз,
       мДва.Поле2
   ИЗ
       мДва КАК мДва) КАК мрез2
ИТОГИ
   СУММА(Раз)
ПО
   ОБЩИЕ
38 Homer
 
28.06.12
13:12
(37) а так работает
39 Ненавижу 1С
 
гуру
28.06.12
13:13
(38) да вроде и (34) работало
40 Homer
 
28.06.12
13:14
(39) пример не удачный, (37) тоже не работает, опять же пример не удачный
41 Ненавижу 1С
 
гуру
28.06.12
13:15
(40) что значит "пример неудачный"? запрос должен работать на любых данных
42 Homer
 
28.06.12
13:16
вот в том то и дела беру другие данные и уже не работает
43 Cyberhawk
 
28.06.12
13:17
(41) сколько у тебя строк в запросе?
44 Cyberhawk
 
28.06.12
13:17
(42) + не считая формирования входных данных
45 Buster007
 
28.06.12
13:18
боюсь, что если такое задание использовать в качестве теста при приеме на работу, то это сразу от 130 ))
46 Ненавижу 1С
 
гуру
28.06.12
13:18
(44) 52 вроде, с форматированием конструктором
47 Ненавижу 1С
 
гуру
28.06.12
13:19
(45) это же хорошо
48 Alex S D
 
28.06.12
13:20
у ненавижу работы нету, сам ставит себе задачи, решает их , а потом не дает работать остальным))
49 Ненавижу 1С
 
гуру
28.06.12
13:21
(48) завидовать не хорошо
50 Alex S D
 
28.06.12
13:22
я же белой завистью..)
51 Cyberhawk
 
28.06.12
13:22
(46) задай на вход таблицу
-5 -3
-10 -12
0 0

Работает?
52 Cyberhawk
 
28.06.12
13:23
А, пардон, 0-0 убрать, не подходит по условию
53 mikecool
 
28.06.12
13:23
(18) ты мне мозг сломал )
54 Ненавижу 1С
 
гуру
28.06.12
13:24
(52) -10 -12 тоже нельзя
55 Cyberhawk
 
28.06.12
13:27
(54) хитер :)
56 Eugene_life
 
28.06.12
13:37
фактически нужно посчитать количество "разрывов"
57 andrewks
 
28.06.12
13:39
лень читать всю ветку, задача ещё актуальна?
58 Eugene_life
 
28.06.12
13:40
(57) да
59 Ненавижу 1С
 
гуру
28.06.12
13:41
(56) количество разрывов ничего не даст
(57) ждем твоего решения
60 Eugene_life
 
28.06.12
13:42
(59) Количество и длина разрывов )
61 andrewks
 
28.06.12
13:42
(59) 2. гы. да я только в ветку забрёл. щас буду думать.

на всякий: отрезки на положительной "части" оси, или могут быть и в минусе?
62 mikecool
 
28.06.12
13:44
плохо что в полях выборки незя использовать подзапросы (
63 Ненавижу 1С
 
гуру
28.06.12
13:46
(61) это несущественно
64 Эмбеддер
 
28.06.12
13:55
Рекурсию можно использовать?
65 Ненавижу 1С
 
гуру
28.06.12
13:58
(64) в запросе? попробуй))
+(46) нашел проще - 30 строк
66 Buster007
 
28.06.12
14:02
ВЫБРАТЬ
   1 КАК А,
   4 КАК Б
ПОМЕСТИТЬ мТаб

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   2,
   6

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   9,
   12

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   10,
   20

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   45,
   46
 
;

////////////////////////////////////////////////////////////////////////////////

Выбрать
Минимум(Т1.А),
Т2.Б
Поместить ПредварительныеОтрезки
из мТаб как т1
Левое соединение мТаб как Т2
по т1.А < т2.А И т1.Б > т2.А
ГДЕ НЕ Т2.Б Есть NULL
Сгруппировать ПО
Т2.Б
;
Выбрать
Т1.А,
Т3.Б
Поместить ВозможныеИзмененияМаксимальнойГраницы
из мТаб как т1
Левое соединение мТаб как Т2
по т1.А < т2.А И т1.Б > т2.А
Левое Соединение мТаб как Т3
По Т1.А = Т3.А
ГДЕ
Т2.Б Есть NULL
;
Выбрать РАЗЛИЧНЫЕ
Т1.А,
ЕстьNULL(Т2.Б, Т1.Б) как Б
Поместить ОтрезкиСВнутреннимиОтрезками
Из
ПредварительныеОтрезки как Т1
Левое соединение ВозможныеИзмененияМаксимальнойГраницы как Т2
По Т1.А < Т2.А И Т2.А < Т1.Б И Т2.Б > Т1.Б
;
Выбрать
Т1.А,
Т1.Б
Поместить ОтрезкиБезВнутреннихОтрезков
Из ВозможныеИзмененияМаксимальнойГраницы как Т1
Левое соединение ОтрезкиСВнутреннимиОтрезками как Т2
ПО Т1.Б = Т2.Б
ГДЕ Т2.А Есть NULL
;
Выбрать
Сумма(Т1.Б - Т1.А) как Итог
Из
(Выбрать
Т1.А,
Т1.Б
ИЗ ОтрезкиСВнутреннимиОтрезками как Т1

Объединить все

Выбрать
Т1.А,
Т1.Б
ИЗ ОтрезкиБезВнутреннихОтрезков как Т1) как Т1
67 Buster007
 
28.06.12
14:03
(66) вроде без промашек работает )
68 mikecool
 
28.06.12
14:08

ВЫБРАТЬ
   1 КАК А,
   5 КАК Б
ПОМЕСТИТЬ _ВТ_АБ_

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   3,
   7

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   10,
   12

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   16,
   18
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   _ВТ_АБ_.А,
   ЕСТЬNULL(_ВТ_АБ_2.Б, _ВТ_АБ_.Б) КАК Б
ПОМЕСТИТЬ _ВТ_АБ_МаксБ
ИЗ
   _ВТ_АБ_ КАК _ВТ_АБ_
       ЛЕВОЕ СОЕДИНЕНИЕ _ВТ_АБ_ КАК _ВТ_АБ_2
       ПО ((НЕ _ВТ_АБ_.А = _ВТ_АБ_2.А))
           И (_ВТ_АБ_2.А < _ВТ_АБ_.Б)
           И _ВТ_АБ_.А < _ВТ_АБ_2.Б
           И _ВТ_АБ_.Б < _ВТ_АБ_2.Б
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   МИНИМУМ(_ВТ_АБ_МаксБ.А) КАК А,
   _ВТ_АБ_МаксБ.Б
ПОМЕСТИТЬ _ВТ_Результат
ИЗ
   _ВТ_АБ_МаксБ КАК _ВТ_АБ_МаксБ

СГРУППИРОВАТЬ ПО
   _ВТ_АБ_МаксБ.Б
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   СУММА(_ВТ_Результат.Б - _ВТ_Результат.А) КАК Диапазон
ИЗ
   _ВТ_Результат КАК _ВТ_Результат


вначале тестовые данные
69 vicof
 
28.06.12
14:09
(67) нифига

ВЫБРАТЬ
   1 КАК А,
   18 КАК Б
ПОМЕСТИТЬ мТаб

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   5,
   8

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   7,
   9

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   12,
   15
;
70 mikecool
 
28.06.12
14:09
+68 наверное не все учел, а то строк мало получается + мой запрос еще можно укоротить ))
71 mikecool
 
28.06.12
14:10
+70 а, блин, мой только с одним пересечением работает, кажись (((
72 mikecool
 
28.06.12
14:11
+71 на данных из (69) выдает 21 ((
73 Buster007
 
28.06.12
14:12
(69) согласен)
74 mikecool
 
28.06.12
14:15
+72 диапазон 5-9 левый цепляется ((
75 mikecool
 
28.06.12
14:16
+74 надо отслеживать многократное пересечение
вот тут голова опухает - типа сколько же соединений надо
76 rs_trade
 
28.06.12
14:20
хорошо бы в таких веточках писать сразу код для mssms, готовящий таблицы с исходными данными. как принято на sql.ru например.
77 Buster007
 
28.06.12
14:28
ВЫБРАТЬ
   1 КАК А,
   4 КАК Б
ПОМЕСТИТЬ мТаб

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   2,
   6

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   9,
   12

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   10,
   20
ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   45,
   46
 
;

////////////////////////////////////////////////////////////////////////////////

Выбрать
Минимум(Т1.А),
Т2.Б
Поместить ПредварительныеОтрезки
из мТаб как т1
Левое соединение мТаб как Т2
по т1.А < т2.А И т1.Б > т2.А
ГДЕ НЕ Т2.Б Есть NULL
Сгруппировать ПО
Т2.Б
;
Выбрать
Т1.А,
Т3.Б
Поместить ВозможныеИзмененияМаксимальнойГраницы
из мТаб как т1
Левое соединение мТаб как Т2
по т1.А < т2.А И т1.Б > т2.А
Левое Соединение мТаб как Т3
По Т1.А = Т3.А
ГДЕ
Т2.Б Есть NULL

Объединить все
Выбрать Различные
Т1.А,
Т2.Б
ИЗ ПредварительныеОтрезки как Т1
Внутреннее соединение мТаб как Т2
ПО т1.А = т2.А и Т1.Б < Т2.Б
;
Выбрать РАЗЛИЧНЫЕ
Т1.А,
Максимум(ЕстьNULL(Т2.Б, Т1.Б)) как Б
Поместить ОтрезкиСВнутреннимиОтрезками
Из
ПредварительныеОтрезки как Т1
Левое соединение ВозможныеИзмененияМаксимальнойГраницы как Т2
По Т1.А <= Т2.А И Т2.А < Т1.Б И Т2.Б > Т1.Б
Сгруппировать ПО т1.А
;
Выбрать
Т1.А,
Т1.Б
Поместить ОтрезкиБезВнутреннихОтрезков
Из ВозможныеИзмененияМаксимальнойГраницы как Т1
Левое соединение ОтрезкиСВнутреннимиОтрезками как Т2
ПО Т1.Б = Т2.Б
ГДЕ Т2.А Есть NULL
;
Выбрать
Сумма(Т1.Б - Т1.А) как Итог
Из
(Выбрать
Т1.А,
Т1.Б
ИЗ ОтрезкиСВнутреннимиОтрезками как Т1

Объединить все

Выбрать
Т1.А,
Т1.Б
ИЗ ОтрезкиБезВнутреннихОтрезков  как Т1
Левое Соединение ОтрезкиСВнутреннимиОтрезками как Т2
По Т1.А> Т2.А И Т1.А < Т2.Б
ГДЕ Т2.А Есть NULL) как Т1
78 Buster007
 
28.06.12
14:28
(77) теперь должно работать ))
79 Buster007
 
28.06.12
14:30
+(78) не, не работает ) ща )
80 GomerSimpson
 
28.06.12
14:30
ВЫБРАТЬ
   СУММА(ВТ.Б - ВТ.А) КАК ДлинаНепересекающихся
ПОМЕСТИТЬ НеПересекающиеся
ИЗ
   ВТ КАК ВТ
       ЛЕВОЕ СОЕДИНЕНИЕ ВТ КАК ВТ1
       ПО (ВТ.А < ВТ1.Б
                   И ВТ.А > ВТ1.А
               ИЛИ ВТ.Б < ВТ1.Б
                   И ВТ.Б > ВТ1.А)
ГДЕ
   ВТ1.Ссылка ЕСТЬ NULL
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   МИНИМУМ(ВТ.А) КАК А,
   МАКСИМУМ(ВТ.Б) КАК Б
ПОМЕСТИТЬ Пересекающиеся
ИЗ
   ВТ КАК ВТ
       ЛЕВОЕ СОЕДИНЕНИЕ ВТ КАК ВТ1
       ПО (ВТ.А < ВТ1.Б
                   И ВТ.А > ВТ1.А
               ИЛИ ВТ.Б < ВТ1.Б
                   И ВТ.Б > ВТ1.А)
ГДЕ
   НЕ ВТ1.Ссылка ЕСТЬ NULL
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   НеПересекающиеся.ДлинаНепересекающихся + Пересекающиеся.Б - Пересекающиеся.А
ИЗ
   НеПересекающиеся КАК НеПересекающиеся,
   Пересекающиеся КАК Пересекающиеся
81 Buster007
 
28.06.12
14:32
вот

ВЫБРАТЬ
   1 КАК А,
   20 КАК Б
ПОМЕСТИТЬ мТаб

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   2,
   6

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   9,
   12

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   10,
   19
ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   18,
   46
 
;

////////////////////////////////////////////////////////////////////////////////

Выбрать
Минимум(Т1.А),
Т2.Б
Поместить ПредварительныеОтрезки
из мТаб как т1
Левое соединение мТаб как Т2
по т1.А < т2.А И т1.Б > т2.А
ГДЕ НЕ Т2.Б Есть NULL
Сгруппировать ПО
Т2.Б
;
Выбрать
Т1.А,
Т3.Б
Поместить ВозможныеИзмененияМаксимальнойГраницы
из мТаб как т1
Левое соединение мТаб как Т2
по т1.А < т2.А И т1.Б > т2.А
Левое Соединение мТаб как Т3
По Т1.А = Т3.А
ГДЕ
Т2.Б Есть NULL

Объединить все
Выбрать Различные
Т1.А,
Т2.Б
ИЗ ПредварительныеОтрезки как Т1
Внутреннее соединение мТаб как Т2
ПО т1.А = т2.А и Т1.Б < Т2.Б
;
Выбрать РАЗЛИЧНЫЕ
Т1.А,
Максимум(ЕстьNULL(Т2.Б, Т1.Б)) как Б
Поместить ОтрезкиСВнутреннимиОтрезками
Из
ПредварительныеОтрезки как Т1
Левое соединение ВозможныеИзмененияМаксимальнойГраницы как Т2
По Т1.А <= Т2.А И Т2.А < Т1.Б И Т2.Б > Т1.Б
Сгруппировать ПО т1.А
;
Выбрать
Т1.А,
Т1.Б
Поместить ОтрезкиБезВнутреннихОтрезков
Из ВозможныеИзмененияМаксимальнойГраницы как Т1
Левое соединение ОтрезкиСВнутреннимиОтрезками как Т2
ПО Т1.Б = Т2.Б
ГДЕ Т2.А Есть NULL
;
Выбрать
Сумма(Т1.Б - Т1.А) как Итог
Из
(Выбрать
Т1.А,
Т1.Б
ИЗ ОтрезкиСВнутреннимиОтрезками как Т1

Объединить все

Выбрать
Т1.А,
Т1.Б
ИЗ ОтрезкиБезВнутреннихОтрезков  как Т1
Левое Соединение ОтрезкиСВнутреннимиОтрезками как Т2
По Т1.А>= Т2.А И Т1.А <= Т2.Б
ГДЕ Т2.А Есть NULL) как Т1
82 ssh2012
 
28.06.12
14:33
(80) > ВТ1.Ссылка  o_O
83 mikecool
 
28.06.12
14:34
все, надоело думать )))
84 Buster007
 
28.06.12
14:34
(80) а откуда ссылка взялась?)
85 mikecool
 
28.06.12
14:34
в моем алгоритме где то небольшой косяк )))
86 ssh2012
 
28.06.12
14:35
(84) не работает

ВЫБРАТЬ
   1 КАК А,
   2 КАК Б
ПОМЕСТИТЬ мТаб

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   1,
   3

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   2,
   3

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   1,
   4

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   3,
   5

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   4,
   10
;
87 Eugene_life
 
28.06.12
14:36
(81) Если подставить в конце
ВЫБРАТЬ
   20,
   46
то выдает 19 :))))
88 Ненавижу 1С
 
гуру
28.06.12
14:36
(76) ок, вот заготовочка


ВЫБРАТЬ
   1 КАК А,
   4 КАК Б
ПОМЕСТИТЬ Т

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   2,
   5

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   7,
   9

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   9,
   10
;
89 Buster007
 
28.06.12
14:38
(87) гм, не предусмотрел, что в А и Б в разных отрезках будет одинаковое число )
ну эт фигня )
90 ssh2012
 
28.06.12
14:39
(88) проверь свой данными (86). работает?
91 Ненавижу 1С
 
гуру
28.06.12
14:40
(90) выдает 9
92 ssh2012
 
28.06.12
14:40
(91) ок
93 mikecool
 
28.06.12
14:42
а у меня - 7 (
94 GomerSimpson
 
28.06.12
14:43
ВЫБРАТЬ
   СУММА(ВТ.Б - ВТ.А) КАК ДлинаНепересекающихся
ПОМЕСТИТЬ НеПересекающиеся
ИЗ
   ВТ КАК ВТ
       ЛЕВОЕ СОЕДИНЕНИЕ ВТ КАК ВТ1
       ПО (ВТ.А < ВТ1.Б
                   И ВТ.А > ВТ1.А
               ИЛИ ВТ.Б < ВТ1.Б
                   И ВТ.Б > ВТ1.А)
                               ГДЕ
   ВТ1.А ЕСТЬ NULL
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   МИНИМУМ(ВТ.А) КАК А,
   МАКСИМУМ(ВТ.Б) КАК Б
ПОМЕСТИТЬ Пересекающиеся
ИЗ
   ВТ КАК ВТ
       ЛЕВОЕ СОЕДИНЕНИЕ ВТ КАК ВТ1
       ПО (ВТ.А < ВТ1.Б
                   И ВТ.А > ВТ1.А
               ИЛИ ВТ.Б < ВТ1.Б
                   И ВТ.Б > ВТ1.А)
ГДЕ
   НЕ ВТ1.А ЕСТЬ NULL
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   НеПересекающиеся.ДлинаНепересекающихся + Пересекающиеся.Б - Пересекающиеся.А
ИЗ
   НеПересекающиеся КАК НеПересекающиеся,
   Пересекающиеся КАК Пересекающиеся
95 Buster007
 
28.06.12
14:44
(91)
ВЫБРАТЬ
   1 КАК А,
   4 КАК Б
ПОМЕСТИТЬ Т

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   2,
   5

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   2,
   9

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   9,
   10

с такими данными что выдает?
96 Buster007
 
28.06.12
14:45
+(95) у меня херню ))
97 Эмбеддер
 
28.06.12
14:45
(94) да, решение должно быть таким. красивым
98 ssh2012
 
28.06.12
14:45
(94) на (86) длига null :))
99 Ненавижу 1С
 
гуру
28.06.12
14:45
(95) 9
100 ssh2012
 
28.06.12
14:45
*длина
101 Buster007
 
28.06.12
15:01
ну всё ) по последним данным всё работает прекрасно )


ВЫБРАТЬ
   1 КАК А,
   4 КАК Б
ПОМЕСТИТЬ мТаб

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   2,
   5
   
ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   6,
   13

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   10,
   11

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   9,
   10
   
   
   ;

////////////////////////////////////////////////////////////////////////////////


Выбрать
Минимум(Т1.А),
Т2.Б
Поместить ПредварительныеОтрезки

из мТаб как т1
Левое соединение мТаб как Т2
по т1.А < т2.А И т1.Б > т2.А
ГДЕ НЕ Т2.Б Есть NULL

Сгруппировать ПО
Т2.Б
;
Выбрать
Т1.А,
Т3.Б
Поместить ВозможныеИзмененияМаксимальнойГраницы

из мТаб как т1
Левое соединение мТаб как Т2
по т1.А < т2.А И т1.Б > т2.А
Левое Соединение мТаб как Т3
По Т1.А = Т3.А
ГДЕ
Т2.Б Есть NULL

Объединить все
Выбрать Различные
Т1.А,
Т2.Б

ИЗ ПредварительныеОтрезки как Т1
Внутреннее соединение мТаб как Т2
ПО т1.А = т2.А и Т1.Б < Т2.Б

;
Выбрать РАЗЛИЧНЫЕ
Т1.А,
Максимум(ЕстьNULL(Т2.Б, Т1.Б)) как Б
Поместить ОтрезкиСВнутреннимиОтрезками
Из

ПредварительныеОтрезки как Т1
Левое соединение ВозможныеИзмененияМаксимальнойГраницы как Т2
По Т1.А <= Т2.А И Т2.А <= Т1.Б И Т2.Б > Т1.Б
Сгруппировать ПО т1.А

;
Выбрать Различные
Т1.А,
Т1.Б
Поместить ОтрезкиБезВнутреннихОтрезков

Из ВозможныеИзмененияМаксимальнойГраницы как Т1
Левое соединение ОтрезкиСВнутреннимиОтрезками как Т2
ПО Т1.Б = Т2.Б
ГДЕ Т2.А Есть NULL

;
Выбрать
Сумма(Т1.Б - Т1.А) как Итог
Из
(Выбрать
Т1.А,
Т1.Б

ИЗ ОтрезкиСВнутреннимиОтрезками как Т1

Объединить все

Выбрать
Т1.А,
Т1.Б

ИЗ ОтрезкиБезВнутреннихОтрезков  как Т1
Левое Соединение ОтрезкиСВнутреннимиОтрезками как Т2
По Т1.А>= Т2.А И Т1.А <= Т2.Б
ГДЕ Т2.А Есть NULL) как Т1
102 ssh2012
 
28.06.12
15:03
(101) на (86) ошибка
103 Buster007
 
28.06.12
15:10
(102) я конечно исправил )
но стоит ли уже захламлять форум?))
104 Ненавижу 1С
 
гуру
28.06.12
15:12
(103) давать свое решение?
105 Buster007
 
28.06.12
15:13
(104) ога ) тем более, что оно как-то не смотрится ))
106 alexhtn
 
28.06.12
15:17
Сначала суммирую все отрезки, а потом отнимаю пересекающиеся интервалы

ВЫБРАТЬ
   Данные.ПолеБ - Данные.ПолеА + 1 КАК Сумма
ПОМЕСТИТЬ Итоговая
ИЗ
   Данные КАК Данные

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   -(Данные1.ПолеБ - Данные2.ПолеА + 1)
ИЗ
   Данные КАК Данные1
       ВНУТРЕННЕЕ СОЕДИНЕНИЕ Данные КАК Данные2
       ПО Данные1.ПолеБ > Данные2.ПолеА
           И Данные1.ПолеБ < Данные2.ПолеБ
           И Данные1.ПолеА < Данные2.ПолеА
           И Данные1.ПолеБ > Данные2.ПолеА
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   СУММА(Итоговая.Сумма) КАК Сумма
ИЗ
   Итоговая КАК Итоговая
107 Ненавижу 1С
 
гуру
28.06.12
15:18
ВЫБРАТЬ
   1 КАК А,
   2 КАК Б
ПОМЕСТИТЬ Т

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   1,
   3

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   2,
   3

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   1,
   4

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   3,
   5

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
   4,
   10
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   Т1.А
ПОМЕСТИТЬ Левые
ИЗ
   Т КАК Т1
       ЛЕВОЕ СОЕДИНЕНИЕ Т КАК Т2
       ПО Т1.А > Т2.А
           И Т1.А <= Т2.Б

СГРУППИРОВАТЬ ПО
   Т1.А

ИМЕЮЩИЕ
   КОЛИЧЕСТВО(Т2.А) = 0
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   Т1.Б
ПОМЕСТИТЬ Правые
ИЗ
   Т КАК Т1
       ЛЕВОЕ СОЕДИНЕНИЕ Т КАК Т2
       ПО Т1.Б < Т2.Б
           И Т1.Б >= Т2.А

СГРУППИРОВАТЬ ПО
   Т1.Б

ИМЕЮЩИЕ
   КОЛИЧЕСТВО(Т2.Б) = 0
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   Левые.А,
   МИНИМУМ(Правые.Б) КАК Б
ПОМЕСТИТЬ Объединение
ИЗ
   Левые КАК Левые
       ВНУТРЕННЕЕ СОЕДИНЕНИЕ Правые КАК Правые
       ПО Левые.А < Правые.Б

СГРУППИРОВАТЬ ПО
   Левые.А
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
   СУММА(Объединение.Б) - СУММА(Объединение.А) КАК Поле1
ИЗ
   Объединение КАК Объединение
108 Ненавижу 1С
 
гуру
28.06.12
15:19
(106) неправильно он работает
109 sergeante
 
28.06.12
15:23
да ну вас нафиг, загрузили ужс
110 andrewks
 
28.06.12
15:27
(107) примерно в эту сторону и думал, но сформулировать не успел :(

решения для таких задачек нужно как минимум до след.дня  придерживать, а то на работе не сели так, что аж некогда задачки с мисты решать :)
111 Ненавижу 1С
 
гуру
28.06.12
15:30
(110) а у меня назрело обобщение ))

Есть таблица Т с числовыми полями А1, Б1, А2, Б2 и А1<А2, Б1<Б2 всегда
Каждая запись таблицы интерпретируется как прямоугольник с координатами противоположных вершин (А1,Б1) и (А2,Б2) на координатной плоскости и сторонами параллельными осям координат

Берется объединение всех прямоугольников

Найти площадь объединения
112 Эмбеддер
 
28.06.12
15:33
(106) что он выдаст, если взять 3 одинаковых отрезка?
113 andrewks
 
28.06.12
16:05
(111) э-э-э... я, может, чё-то недопонял, но, мне кажется. не взлетит.

объединение прямоугольников не есть множество прямоугольников, в отличие от отрезков
114 rs_trade
 
28.06.12
16:12
оно?

declare t table (id int, a int, b int)
insert t values
(1,    1, 5),
(2,    2, 11),
(3,    18,21),
(4,    20,30)

select
   sum(case
       when isnull(t2.b-t2.a, 0) > t1.a then
           t1.b - isnull(t2.b-t2.a, t1.a)
       else
           t1.b - t1.a
       end)
from
   t t1
   left join t t2
       on t2.id = t1.id-1
115 rs_trade
 
28.06.12
16:14
(114) круть какая получилась. оказывается есть юзер t
116 andrewks
 
28.06.12
16:14
select from registered-user  порадовало :)))
117 rs_trade
 
28.06.12
16:16
может так прокатит

declare @tbl table (id int, a int, b int)
insert @tbl values
(1,    1, 5),
(2,    2, 11),
(3,    18,21),
(4,    20,30)

select
   sum(case
       when isnull(t2.b-t2.a, 0) > t1.a then
           t1.b - isnull(t2.b-t2.a, t1.a)
       else
           t1.b - t1.a
       end)
from
   @tbl t1
   left join @tbl t2
       on t2.id = t1.id-1
118 andrewks
 
28.06.12
16:19
(117)  попробуй с такими входными данными:

insert @tbl values
(1,    1, 5),
(2,    2, 11),
(3,    2, 11),
(4,    2, 11)

что выдаст?
119 Ненавижу 1С
 
гуру
28.06.12
16:28
(113) да, не является, в том и соль
120 rs_trade
 
28.06.12
16:32
(118) угу. у меня еще и отрезки по возрастающей идут. не годится.
121 rs_trade
 
28.06.12
18:43
а если вот таким макаром еще забацать ))

declare @tbl table (id int, a int, b int)
insert @tbl values
(1,    1, 5)
,(2,    2, 11)
,(3,    18, 21)
,(4,    20, 30)
,(5,    2, 11)
;
with cte1 as
(
select
   v1.number
from
   @tbl as t1
       left join master..spt_values v1
           on v1.number > t1.a and v1.number <= t1.b and v1.type ='P'
group by
   v1.number
)

select count(*) from cte1
122 andrewks
 
28.06.12
19:28
(119) да это вывих мозга. уникальность строки таблицы можно взять в условии, или ты и без этого решил?

а про прикладной смысл задачки из (0) я допетрил - это расчёт стажа в запросе, верно?
123 Ненавижу 1С
 
гуру
28.06.12
22:29
(122) никаких уникальностей, а смысл?
прикладного смысла не было, но так тоже можно
124 Ненавижу 1С
 
гуру
29.06.12
08:56
задача из (111) наталкивает и на еще одно решение задачи в (0)
разбиваем на элементарный прямоугольники/параллелепипеды/отрезки (всеми линиями/гранями/точками в выборке)
находим для каждого входит ли он в область
125 ssh2006
 
29.06.12
11:23
Интересная задачка (0)
126 Отчегослик
 
03.07.12
13:15
(111)
ВЫБРАТЬ
   10 КАК А1, 10  КАК Б1, 20 КАК А2, 20 КАК Б2
ПОМЕСТИТЬ Т
   
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
   15, 15, 25, 25

ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
   15, 5, 20, 15
   
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
   10, 15, 20, 30
   
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
   -20, 10, -10, 30
;
   
ВЫБРАТЬ Т.А1 КАК А
ПОМЕСТИТЬ ВсеА
ИЗ Т
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ Т.А2
ИЗ Т;

ВЫБРАТЬ ВсеА.А
ПОМЕСТИТЬ ВсеАГрупп
ИЗ ВсеА
СГРУППИРОВАТЬ ПО ВсеА.А;

ВЫБРАТЬ ВсеАГрупп.А КАК А, КОЛИЧЕСТВО(ВсеАГрупп_1.А) КАК Порядок
ПОМЕСТИТЬ ВсеАУпоряд
ИЗ ВсеАГрупп
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВсеАГрупп КАК ВсеАГрупп_1
ПО ВсеАГрупп.А >= ВсеАГрупп_1.А
СГРУППИРОВАТЬ ПО ВсеАГрупп.А;

ВЫБРАТЬ Т.Б1 КАК Б
ПОМЕСТИТЬ ВсеБ
ИЗ Т
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ Т.Б2
ИЗ Т;

ВЫБРАТЬ ВсеБ.Б
ПОМЕСТИТЬ ВсеБГрупп
ИЗ ВсеБ
СГРУППИРОВАТЬ ПО ВсеБ.Б;

ВЫБРАТЬ ВсеБГрупп.Б КАК Б, КОЛИЧЕСТВО(ВсеБГрупп_1.Б) КАК Порядок
ПОМЕСТИТЬ ВсеБУпоряд
ИЗ ВсеБГрупп
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВсеБГрупп КАК ВсеБГрупп_1
ПО ВсеБГрупп.Б >= ВсеБГрупп_1.Б
СГРУППИРОВАТЬ ПО ВсеБГрупп.Б;

ВЫБРАТЬ ВсеАУпоряд.А, ВсеАУпоряд.Порядок КАК ПорядокА, ВсеБУпоряд.Б, ВсеБУпоряд.Порядок КАК ПорядокБ
ПОМЕСТИТЬ КоординатыУпоряд
ИЗ ВсеАУпоряд
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВсеБУпоряд ПО 1=1;

ВЫБРАТЬ КУ.А КАК А1, КУ.Б КАК Б1, КУ.ПорядокА, КУ.ПорядокБ
ИЗ КоординатыУпоряд КУ;

ВЫБРАТЬ КоординатыУпоряд.А КАК А1, КоординатыУпоряд.Б КАК Б1, КоординатыУпоряд_1.А КАК А2, КоординатыУпоряд_1.Б КАК Б2
ПОМЕСТИТЬ МножествоПрямоугольниковЧастей
ИЗ КоординатыУпоряд
ВНУТРЕННЕЕ СОЕДИНЕНИЕ КоординатыУпоряд КАК КоординатыУпоряд_1
   ПО КоординатыУпоряд_1.ПорядокА = КоординатыУпоряд.ПорядокА + 1
   И КоординатыУпоряд_1.ПорядокБ = КоординатыУпоряд.ПорядокБ + 1;    
   
ВЫБРАТЬ МПЧ.А1, МПЧ.Б1, МПЧ.А2, МПЧ.Б2
ПОМЕСТИТЬ МножествоПрямоугольниковДляРасчета
ИЗ Т
   ВНУТРЕННЕЕ СОЕДИНЕНИЕ МножествоПрямоугольниковЧастей КАК МПЧ
   ПО Т.А1 <= МПЧ.А1 И Т.Б1 <= МПЧ.Б1
   И  Т.А2 >= МПЧ.А2 И Т.Б2 >= МПЧ.Б2

СГРУППИРОВАТЬ ПО МПЧ.А1, МПЧ.Б1, МПЧ.А2, МПЧ.Б2;

ВЫБРАТЬ СУММА( (МПР.А2 - МПР.А1) * (МПР.Б2 - МПР.Б1) )
ИЗ МножествоПрямоугольниковДляРасчета МПР
;