CTEs + Tabelas Sequênciais
Hoje precisei utilizar uma tabela sequencial e lembrei que li um texto do Itzik Ben-Gan mostrando uma alterativa para criar uma tabela sequêncial, eu lembro que ele usou CTEs, CROSS JOIN e ROWNUMBER para fazer a bagaça funcionar… portanto fui testar.
Antigamente eu usava o comando abaixo para obter uma tabela sequencial. Cheguei a escrever sobre isso por aqui… Como remover uso de cursores, utilizando CTEs
WITH CTE_Temp (ID)
AS
(
SELECT 1 AS ID
UNION ALL
SELECT 1 + ID AS ID
FROM CTE_Temp
WHERE ID < 50000
)
SELECT * FROM CTE_Temp
OPTION(MAXRECURSION 0)
GO
Este comando é prático e bem interessante, pois usa a recursividade das CTEs para gerar os números sequenciais… Porém veja a quantidade de IOs que este comando faz.
(50000 row(s) affected)
Tabela ‘Worktable’. Número de verificações 2, leituras lógicas 300001, leituras físicas 0, leituras read-ahead 0, leituras lógicas lob 0, leituras físicas lob 0, leituras read-ahead lob 0.
Uma outra opção seria usar as CTEs em conjunto com CROSS JOINs. Segue um exemplo:
WITH CTE_Temp (ID)
AS
(
SELECT 1 AS ID
UNION ALL
SELECT 1 + ID AS ID
FROM CTE_Temp
WHERE ID < 50000
)
SELECT * FROM CTE_Temp
OPTION(MAXRECURSION 0)
GO
WITH t1 (Tot) AS(SELECT 1 UNION ALL SELECT 1), — 2 linhas
t2 (Tot) AS(SELECT 1 FROM t1 CROSS JOIN t1 AS B), — 4 linhas
t3 (Tot) AS(SELECT 1 FROM t2 CROSS JOIN t2 AS B), — 16 linhas
t4 (Tot) AS(SELECT 1 FROM t3 CROSS JOIN t3 AS B), — 256 linhas
t5 (Tot) AS(SELECT 1 FROM t4 CROSS JOIN t4 AS B), — 65536 linhas
Seq (ID) AS(SELECT TOP 50000 ROW_NUMBER() OVER(ORDER BY (SELECT 1)) FROM t5)
SELECT * FROM Seq
Qual foi o número de IOs que ele fez?… veja o resultado do STATISTICS IO.
(50000 row(s) affected)
Pois é… nenhum… duvida?. Veja uma comparação entre os comandos no profiler.
Show J, vivendo e aprendendo, créditos ao Itzik Ben-Gan gênio.