Em uma oficina, 3 ou mais pessoas trabalham juntas com horários diferentes. Por exemplo, 3 PersonIDs são 5215, 18943 e 21488.
Eu tenho uma tabela tblTimetable
assim:
CREATE TABLE tblTimetable
(
PersonID INT,
TimetableID INT
);
INSERT INTO tblTimetable (PersonID, TimetableID)
VALUES (5215, 57), (18943, 221), (18943, 230), (18943, 238),
(21488, 257), (21488, 270), (5215, 67), (5215, 77),
(5215, 87), (5215, 97);
Com esta seleção:
SELECT PersonID, TimetableID
FROM tblTimetable
Recebo este conjunto de linhas de origem:
PersonID TimetableID
5215 57
18943 221
18943 230
18943 238
21488 257
21488 270
5215 67
5215 77
5215 87
5215 97
Cada par (PersonID, TimetableID) é um bloco sólido imutável. Gostaria de selecionar todas as combinações de pares (PersonID, TimetableID).
Cada TimetableID é definido em uma tabela separada tblTimetableDetail
; aqui, ele não é manipulado, mas será consultado posteriormente para plotagem em um relatório do Microsoft Access.
CREATE TABLE tblTimetableDetail
(
TimetableID INT,
WeekdayID INT,
BeginTime DATETIME,
EndTime DATETIME
);
Até agora eu tentei isso:
SELECT PersonID, MIN(TimetableID)
FROM tblTimetable
GROUP BY PersonID
UNION ALL
SELECT PersonID, MAX(TimetableID)
FROM tblTimetable
GROUP BY PersonID
Recebi duas combinações de pares PersonID e TimetableID:
PersonID TimetableID
5215 57
18943 221
21488 257
5215 97
18943 238
21488 270
Gostaria de obter a lista exaustiva de combinações de pares PersonID - TimetableID, todos os PersonID's devem estar presentes em qualquer combinação. Mas a ordem não importa:
CombiNo PersonID TimetableID
1 5215 57
1 18943 221
1 21488 257
2 5215 57
2 18943 221
2 21488 270
3 5215 57
3 18943 230
3 21488 257
4 5215 57
4 18943 230
4 21488 270
5 5215 57
5 18943 238
5 21488 257
6 5215 57
6 18943 238
6 21488 270
7 5215 67
7 18943 221
7 21488 257
8 5215 67
8 18943 221
8 21488 270
9 5215 67
9 18943 230
9 21488 257
10 5215 67
10 18943 230
10 21488 270
11 5215 67
11 18943 238
11 21488 257
12 5215 67
12 18943 238
12 21488 270
13 5215 77
13 18943 221
13 21488 257
14 5215 77
14 18943 221
14 21488 270
15 5215 77
15 18943 230
15 21488 257
16 5215 77
16 18943 230
16 21488 270
17 5215 77
17 18943 238
17 21488 257
18 5215 77
18 18943 238
18 21488 270
19 5215 87
19 18943 221
19 21488 257
20 5215 87
20 18943 221
20 21488 270
21 5215 87
21 18943 230
21 21488 257
22 5215 87
22 18943 230
22 21488 270
23 5215 87
23 18943 238
23 21488 257
24 5215 87
24 18943 238
24 21488 270
25 5215 97
25 18943 221
25 21488 257
26 5215 97
26 18943 221
26 21488 270
27 5215 97
27 18943 230
27 21488 257
28 5215 97
28 18943 230
28 21488 270
29 5215 97
29 18943 238
29 21488 257
30 5215 97
30 18943 238
30 21488 270
Como fazer isso com T-SQL?
Com uma boa string SQL, posso fazer uma consulta PassThrough como .RecordSource para um relatório, desenhando 30 páginas de cronograma, cada combinação por página.
https://dbfiddle.uk/PLiK04hT
Cabe a você converter as matrizes JSON em linhas usando a sintaxe do SQLServer.
(Versão ORACLE como exemplo: https://dbfiddle.uk/6VGG4Uad )
Podemos considerar essa tarefa como fazer combinações únicas dos membros de um conjunto - cada combinação deve ter 1 membro de cada conjunto.
Com esses dados de teste temos 3 conjuntos
Então a contagem de combinações é 5*3*2=30 -
totOver
.Podemos multiplicar (gerar séries) cada linha para (totOver/rQty) linhas.
Por exemplo
O último número no triplo é o número do grupo.
Veja o exemplo
PrepRn
saída.....
violino
violino
Desde que você tenha acesso ao
GENERATE_SERIES()
SQL Server 2022 em diante, não precisará de recursão ou junções, apenas um pouco de matemática e duplicação de linhas com IDs apropriadas.No seu caso, existem 30 combinações (
5 from person A
*3 from person B
*2 from person c
==30
)Isto significa que:
cada linha
person A
precisa ser duplicada 6 vezescada linha
person B
precisa ser duplicada 10 vezescada linha
person C
precisa ser duplicada 15 vezesCada duplicado precisa de um
combo_id
, por exemplo, paraperson A
:Isso pode ser obtido com
GENERATE_SERIES(original_row_id, 30, 5)
onde30
é o número total de combinações e5
é o número de linhas que a correnteperson
possui.Using
CROSS APPLY
means that we can generate a different series (generating different number of duplicates, with differingcombination_d
values) for each person and each of their rows.fiddle
Tente remover os hits para x da tabela original, como nesta consulta cte. Você pode preparar um procedimento armazenado com base nessa lógica ou adicionar recursividade para a consulta cte, se possível (desculpe, não sou bom nisso.)
Faça uma junção cruzada de 3 vias. Uma pessoa dada não será escolhida mais de uma vez por causa das desigualdades.