:: Не фоксом единым
Таблица группы (вертикальная в горизонтальную)
VeterVFP
Автор

Сообщений: 413
Откуда: Москва
Дата регистрации: 26.12.2006
Приветствую.
Есть вертикальная таблица с номерами, объединенными в группы:
Группа, Номер
01 1.1
01 1.2
01 1.3
02 2.1
02 2.2
Как оптимально получить из нее горизонтальную цепочку для каждой группы (по принципу "каждый с каждым")?
Я так понимаю, что-то типа транспонирования, но мне ничего агрегатного не нужно, лишь цепочку.
Можно ли SQL-ем или придется таки цикл крутить по номерам?

Т.е. из Grps_Vert получить Grps_Horiz
CREATE CURSOR Grps_Vert (Gr C(2), Nomer C(3))
INSERT INTO Grps_Vert VALUES ('01', '1.1')
INSERT INTO Grps_Vert VALUES ('01', '1.2')
INSERT INTO Grps_Vert VALUES ('01', '1.3')
INSERT INTO Grps_Vert VALUES ('01', '1.4')
INSERT INTO Grps_Vert VALUES ('02', '2.1')
INSERT INTO Grps_Vert VALUES ('02', '2.2')
LOCATE
BROWSE LAST NOWAIT
CREATE CURSOR Grps_Horiz (Nomer1 C(3), Nomer2 C(3))
INSERT INTO Grps_Horiz VALUES ('1.1', '1.2')
INSERT INTO Grps_Horiz VALUES ('1.1', '1.3')
INSERT INTO Grps_Horiz VALUES ('1.1', '1.4')
INSERT INTO Grps_Horiz VALUES ('1.2', '1.3')
INSERT INTO Grps_Horiz VALUES ('1.2', '1.4')
INSERT INTO Grps_Horiz VALUES ('1.3', '1.4')
INSERT INTO Grps_Horiz VALUES ('2.1', '2.2')
LOCATE
BROWSE LAST NOWAIT
Ratings: 0 negative/0 positive
Re: Таблица группы (вертикальная в горизонтальную)
PaulWist

Сообщений: 14601
Дата регистрации: 01.04.2004
Транспорировать надо в фоксе?

Если в MSSQL, то Pivot.


------------------
Есть многое на свете, друг Горацио...
Что и не снилось нашим мудрецам.
(В.Шекспир Гамлет)
Ratings: 0 negative/0 positive
Re: Таблица группы (вертикальная в горизонтальную)
spinz

Сообщений: 5263
Дата регистрации: 21.01.2016
нифига не понял, но лефтджойн по полю группы разве не?


------------------
Позовите санитаров
Ratings: 0 negative/0 positive
Re: Таблица группы (вертикальная в горизонтальную)
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
SELECT c1.Nomer Nomer1, c2.Nomer Nomer2 ;
FROM Grps_Vert c1 INNER JOIN Grps_Vert c2 ;
ON c1.Gr =c2.Gr AND c1.Nomer < c2.Nomer ;
ORDER BY c1.Nomer, c2.Nomer

Требует уникальности Nomer в рамках каждой отдельной группы, иначе некоторая лажа в результате будет. Если исходные данные не отвечают таким условиям, прогони их через группировку или банальный DISTINCT.

К "транспонированию", т.е. "повороту", превращению записей в поля, а полей в записи это не имеет никакого отношения.

P.S. Это определённый вариант картезианского произведения ("уполовиненный" по сути), т.е. если в группе будет, скажем, 100 записей, то в итоговой выборке их станет уже около 5 тысяч


------------------
WBR, Igor




Исправлено 1 раз(а). Последнее : Igor Korolyov, 11.05.18 18:52
Ratings: 0 negative/0 positive
Re: Таблица группы (вертикальная в горизонтальную)
of63

Сообщений: 25161
Откуда: Н.Новгород
Дата регистрации: 13.02.2008
В формате SELECT-запорса опять не осилил...

В примере ТС, вероятно, полагается, что:
- для каждой группы (Gr) записей (группы никак не пересекаются друг с другом) надо получить
- все возможные комбинации пар значений (Nomer)

Т.к. группы не пересекаются, то можно все это изложить просто до попарного перебора. Схематично:
CREATE (m.b) (N1, N2) && выходная таблица
* SET FILTER TO Gr=m.группа && группы получены DISTINCT-снимком из исходной таблички. Переберем их в FOR EACH m.группа
SELECT (m.a) && исходная таблица
SCAN
m.r = RECNO()
m.x = Nomer
SCAN FOR RECNO()>m.r && перебираем записи НИЖЕ каждой текущей
INSERT INTO (m.b) VALUES (m.x, Nomer)
ENDSCAN
GO RECORD (m.r)
ENDSCAN && исходная таблица
Ratings: 1 negative/0 positive
Re: Таблица группы (вертикальная в горизонтальную)
VeterVFP
Автор

Сообщений: 413
Откуда: Москва
Дата регистрации: 26.12.2006
Пардон, по ошибке залепил тему не в тот раздел. Просьба в ФОКС перенести!.
Нужно все это в VFP9.
Игорь верно понял - похоже, получилось то, что надо! Спасибо!



Исправлено 1 раз(а). Последнее : VeterVFP, 14.05.18 12:47
Ratings: 0 negative/0 positive
Re: Таблица группы (вертикальная в горизонтальную)
VeterVFP
Автор

Сообщений: 413
Откуда: Москва
Дата регистрации: 26.12.2006
Появилось доп условие для отбора по наличию признака у номера.
Репро такой:
CREATE CURSOR Grps_Vert (Gr C(2), Prizn C(2), Nomer C(3))
INSERT INTO Grps_Vert VALUES ('01', 'AA', '1.1')
INSERT INTO Grps_Vert VALUES ('01', 'BB', '1.2')
INSERT INTO Grps_Vert VALUES ('01', 'AA', '1.3')
INSERT INTO Grps_Vert VALUES ('01', 'CC', '1.4')
INSERT INTO Grps_Vert VALUES ('02', 'AA', '2.1')
INSERT INTO Grps_Vert VALUES ('02', 'AA', '2.2')
INSERT INTO Grps_Vert VALUES ('03', 'AA', '3.2')
LOCATE
BROWSE LAST NOWAIT
***
cPr= ''
cPr= 'AA'
IF EMPTY(cPr)
SELECT C1.Prizn P1, C1.Nomer Nomer1, C2.Prizn P2, C2.Nomer Nomer2;
FROM Grps_Vert C1;
INNER JOIN Grps_Vert C2 ON (C1.Gr=C2.Gr) AND (C1.Nomer < C2.Nomer);
ORDER BY C1.Nomer, C2.Nomer;
INTO CURSOR Result_Curs
ELSE
SELECT C1.Prizn P1, C1.Nomer Nomer1, C2.Prizn P2, C2.Nomer Nomer2;
FROM Grps_Vert C1;
INNER JOIN Grps_Vert C2 ON (C1.Gr=C2.Gr) AND (C1.Nomer <> C2.Nomer);
WHERE C1.Prizn= cPr;
ORDER BY C1.Nomer, C2.Nomer;
INTO CURSOR Result_Curs
ENDIF
LOCATE
BROWSE LAST NOWAIT
При наличии ограничивающего признака нужно также получить пары номеров, но уже только те, где этот признак = cPr.
Сделал условие отбора (в ветке ELSE) - список получается верный по сути, но с дублированием пар, где у обоих номеров признак одинаковый (только зеркально).
Т.е. из репро получается такие дубли:
АА / 1.1 - АА / 1.3
АА / 1.3 - АА / 1.1
АА / 2.1 - АА / 2.2
АА / 2.2 - АА / 2.1
Как их убрать?


2 moderators: Перекиньте тему в раздел Фокса, плиз!
Ratings: 0 negative/0 positive
Re: Таблица группы (вертикальная в горизонтальную)
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
Ну так ты ж сам написал во 2 запросе <> вместо < в первом... Так получается картезианское произведение за вычетом "диагонали" сам-с-собой соединённых.
Кроме того, где условие C2.Prizn = m.cPr ?
Я так понимаю надо ж "только из подходящих" пары составлять, а не "подходящие со всеми остальными"...
Кроме того, при штатной установке SET ANSI OFF второй запрос будет работать идентично первому, если в m.cPr будет пустая строка (сравнение до исчерпания более короткой строки - для "пустой" строки это значит что ограничения по сути нет вообще).
Кстати, именно по этой причине стоит при задании cPR для этого запроса всегда его явно дополнять до размера поля - а то пропишешь там "А" и он бодро возьмёт и "А" и "АА" и "АБ" из таблицы...


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Таблица группы (вертикальная в горизонтальную)
VeterVFP
Автор

Сообщений: 413
Откуда: Москва
Дата регистрации: 26.12.2006
Igor Korolyov
Кроме того, где условие C2.Prizn = m.cPr ?
Я так понимаю надо ж "только из подходящих" пары составлять, а не "подходящие со всеми остальными"...
Нет, как раз надо "подходящие со всеми остальными"! Поэтому и условие только по C1.Prizn.
Т.е. результат почти нужный, за исключением этих "зеркальных" дублей, которых может получиться много.
Вот и не пойму, как их убрать.

Igor Korolyov
при штатной установке SET ANSI OFF второй запрос будет работать идентично первому, если в m.cPr будет пустая строка (сравнение до исчерпания более короткой строки - для "пустой" строки это значит что ограничения по сути нет вообще).
Да, это в реальном коде я предусмотрел. Да и пустая по
IF EMPTY(cPr)
уже отсечется.
Ratings: 0 negative/0 positive
Re: Таблица группы (вертикальная в горизонтальную)
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
VeterVFP
Igor Korolyov
Кроме того, где условие C2.Prizn = m.cPr ?
Я так понимаю надо ж "только из подходящих" пары составлять, а не "подходящие со всеми остальными"...
Нет, как раз надо "подходящие со всеми остальными"! Поэтому и условие только по C1.Prizn.
Не вижу логики. Если смотреть "без дублей", то пара должна быть НЕУПОРЯДОЧЕННОЙ - т.е. 1.1-1.2 и 1.2-1.1 по сути одно и то же. и тогда признак учитывать нужно "с обоих сторон". Если же признак учитывается лишь с одной стороны, то твой "результат" сразу некорректен. Где пара
АА/1.1 - BB/1.2
?
И тогда корректное условие должно иметь смысл "хотя бы с одной стороны есть АА" - но никак не "слева есть, справа нет".

Хотя в любом случае это неправильно... Если ЕСТЬ разница между "сторонами", то и результат должен быть "упорядоченным", и 1.1-1.2 и 1.2-1.1 автоматически становятся РАЗНЫМИ парами...

Ну да если "очень хочется", добавь условие OR C2.Prizn = m.cPr вместе с условием C1.Nomer < C2.Nomer. Да, некоторые пары будут "перевёрнуты", но какая разница, если это именно "просто пара", т.е. сочетание двух элементов одного и того-же смысла.
Если нужно именно "упорядоченное" (1.1-1.2 и 1.2-1.1 это совершенно разная штука) - другая задача получается. Наверное через UNION можно сделать.


VeterVFP
Да и пустая по
IF EMPTY(cPr)
уже отсечется.
Речь про то что задача решалась бы ОДНИМ универсальным запросом, безо всяких IF.


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Таблица группы (вертикальная в горизонтальную)
VeterVFP
Автор

Сообщений: 413
Откуда: Москва
Дата регистрации: 26.12.2006
Igor Korolyov
Если смотреть "без дублей", то пара должна быть НЕУПОРЯДОЧЕННОЙ - т.е. 1.1-1.2 и 1.2-1.1 по сути одно и то же. и тогда признак учитывать нужно "с обоих сторон"
Игорь, именно так и надо, т.е. "справа" или "слева" пара - неважно: АА/1.1 - АА/1.2 будет равносильна АА/1.2 - АА/1.1 и именно поэтому и считаются они дублями, которые мне и нужно убрать. Т.е. можно оставить любой вариант из них - сторона "лево" или "право" не важно.
Конечно удобнее было бы с одной стороны иметь все записи по этому признаку, но ПОКА это не существенно.

Igor Korolyov
Если же признак учитывается лишь с одной стороны, то твой "результат" сразу некорректен. Где пара
АА/1.1 - BB/1.2
Хм. Не понял, в репро в результатном курсоре вижу эту пару.

Igor Korolyov
добавь условие OR C2.Prizn = m.cPr вместе с условием C1.Nomer < C2.Nomer.
Ты про такой вариант?
SELECT C1.Prizn P1, C1.Nomer Nomer1, C2.Prizn P2, C2.Nomer Nomer2;
FROM Grps_Vert C1;
INNER JOIN Grps_Vert C2 ON (C1.Gr=C2.Gr) AND (C1.Nomer <> C2.Nomer) AND;
(C1.Nomer < C2.Nomer OR C2.Prizn=cPr);
WHERE C1.Prizn=cPr;
ORDER BY C1.Nomer, C2.Nomer;
INTO CURSOR Result_Curs
Но в этом примере у меня выпадает пара АА/1.3 - ВВ/1.2
Или я не понял твою мысль?
Ratings: 0 negative/0 positive
Re: Таблица группы (вертикальная в горизонтальную)
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
VeterVFP
в репро в результатном курсоре вижу эту пару.
В тексте ты её не указал - вот я и в затруднении - нужна она или уже нет

VeterVFP
Ты про такой вариант?
Нет, не так.
SELECT C1.Prizn P1, C1.Nomer Nomer1, C2.Prizn P2, C2.Nomer Nomer2 ;
FROM Grps_Vert C1 ;
INNER JOIN Grps_Vert C2 ON C1.Gr=C2.Gr AND C1.Nomer < C2.Nomer ;
WHERE C1.Prizn = m.cPr OR C2.Prizn = m.cPr ;
ORDER BY C1.Nomer, C2.Nomer ;
INTO CURSOR Result_Curs
Если всё в ON писать, то будет
SELECT C1.Prizn P1, C1.Nomer Nomer1, C2.Prizn P2, C2.Nomer Nomer2 ;
FROM Grps_Vert C1 ;
INNER JOIN Grps_Vert C2 ON C1.Gr=C2.Gr AND C1.Nomer < C2.Nomer AND ;
(C1.Prizn = m.cPr OR C2.Prizn = m.cPr) ;
ORDER BY C1.Nomer, C2.Nomer ;
INTO CURSOR Result_Curs

Разница между запросом с cPr="AA" и cPr="" лишь в записи BB/1.2-CC/1.4, где ни с одной ни с другой стороны нет нужного АА.
И да, этот запрос ОДИН работает и для заданного и для не заданного (пустого) cPr - лишь бы настройка SET ANSI была в OFF (как оно и есть по умолчанию).
Никаких IF не требуется.


------------------
WBR, Igor
Ratings: 0 negative/0 positive
Re: Таблица группы (вертикальная в горизонтальную)
VeterVFP
Автор

Сообщений: 413
Откуда: Москва
Дата регистрации: 26.12.2006
Игорь, вроде уловил - переделал на 1 запрос. Пока не вижу нестыковок в результатах
Спасибо!
Единственное, что, т.к. это все на свободных ДБФах построено, то при больших выборках начинает зависать прога (а там полу-картезианское может достигать 10ки млн ).
И даже когда я делал сохранение в CSV
COPY TO (cFileSave) CSV AS 866
тоже зависало периодически. Это из-за "тяжелых" объемов?


Исправлено 2 раз(а). Последнее : VeterVFP, 22.05.18 13:39
Ratings: 0 negative/0 positive
Re: Таблица группы (вертикальная в горизонтальную)
Igor Korolyov

Сообщений: 34580
Дата регистрации: 28.05.2002
10М это прилично. Особенно если без оптимизации - т.е. если по ходу дела фокс генерит 100М и без индексов отбрасывает "ненужные" записи - скажем те что "между группами" образуются. А просто выброска dbf в csv (независимо от того free таблица или нет, досовская она или виндовая) - не должна тормозить. Тут если что и мешает, то это вне фокса (АВ, слабая сеть, дохлый жёсткий диск).


------------------
WBR, Igor
Ratings: 0 negative/0 positive


Извините, только зарегистрированные пользователи могут оставлять сообщения в этом форуме.

On-line: 1 (Гостей: 1)

© 2000-2024 Fox Club 
Яндекс.Метрика