none
Dividir registros de uma tabela em partes iguais RRS feed

  • Pergunta

  • Srs, Boa tarde.

    Tenho uma questão que acredito ser relativamente simples.

    Possuo uma tabela SQL com 880mil registros.

    Preciso dividir esta tabela em 5 partes em 5 tabelas diferentes. Poderiam me dar uma luz indicando sobre qual assunto devo pesquisar?

    Abs

    Carlos

    segunda-feira, 4 de agosto de 2014 18:05

Respostas

  • Deleted
    terça-feira, 5 de agosto de 2014 13:27
  • Carlos,

    Desenvolvi um script para tentar te ajudar. 

    Se estivesse no SQL Server 2012 a cláusula OFFSET como indicado pelo Durval seria perfeita, mas como você está no 2008, terá que usar o ROW_NUMBER() mesmo.

    O código abaixo divide sua tabela original em N outras tabelas de acordo com o numero que você especificar (fiz assim caso sua tabela fique maior que os 880 mil registros).

    Fiz o ranking por DDD, mas nada impede que um DDD fique em duas ou mais tabelas, já que você está dividindo em blocos de 200.000

    Substitua abaixo o nome da sua tabela que chamei de "TABELAORIGINAL" e também a lista de campos onde marquei como comentário.
    No script chamei as tabelas que receberão os dados de Tabela1, tabela2 e assim por diante.

    Deixei o comando de execução do INSERT (EXEC(@Comando)) comentado. Basta descomentá-lo após os ajustes.

    SET NOCOUNT ON
    GO
    
    
    CREATE TABLE #TMP
    (
    	NumLinha INT,
    	TabelaDestino Int,
    	-- COLOCAR AQUI A LISTA DE CAMPOS E TIPOS IGUAIS A SUA TABELA ORIGINAL
    )
    
    
    INSERT INTO #tmp
    SELECT ROW_NUMBER() OVER (ORDER BY DDD),  NULL 
    -- COLOCAR AQUI A LISTA DE CAMPOS DA SUA TABELA ORIGINAL
    FROM TabelaOriginal --SUBSTITUIR PELO NOME DA SUA TABELA ORIGINAL
    
    
    
    DECLARE @QtdeRegistros INT
    SET @QtdeRegistros = (SELECT MAX(NumLinha) FROM #TMP)
    DECLARE @NumTabelas FLOAT
    SET @NumTabelas = 2
    
    
    WHILE 1=1
    BEGIN
    
    	IF (SELECT CONVERT(FLOAT, @QtdeRegistros/@NumTabelas)) > 200000 -- NUMERO MÁXIMO DE REGISTROS QUE VOCÊ DESEJA POR TABELA
    	BEGIN
    		SET @NumTabelas = @NumTabelas + 1
    	END
    	ELSE
    	BEGIN
    		BREAK
    	END
    
    END
    
    
    DECLARE @Contador INT = 1
    DECLARE @Contador1 INT = 1
    
    
    WHILE (@Contador <= @QtdeRegistros)
    BEGIN
    
    	UPDATE #TMP
    	SET TabelaDestino = @Contador1
    	WHERE NumLinha >= @contador
    	AND NumLinha < @contador + 2
    
    	SET @Contador = @CONTADOR + 2
    	SET @Contador1 = @Contador1 + 1
    
    
    
    END
    
    
    DECLARE @Comando NVARCHAR(MAX)
    SET @Contador = 1
    
    WHILE (@Contador <= @NumTabelas)
    BEGIN
    
    	SET @Comando = N'INSERT INTO TABELA' + CONVERT(VARCHAR(3), @Contador) 
    	+ ' (LISTA DE CAMPOS DA SUA TABELA ORIGINAL)
    		SELECT LISTA DE CAMPOS DA SUA TABELA ORIGINAL
    		FROM #TMP
    		WHERE TABELADESTINO = ' + CONVERT(VARCHAR(3), @Contador) 
    
    	PRINT @COMANDO
    	--EXEC(@COMANDO) 
    
    	SET @Contador = @Contador + 1
    
    
    END
    
    
    
    DROP TABLE #TMP


    Espero ter ajudado...


    Mariana Del Nero /* Se a resposta foi útil, não esqueça de marcá-la */

    terça-feira, 5 de agosto de 2014 13:02

Todas as Respostas

  • Boa tarde Carlos,

    Sua dúvida é sobre como migrar os dados da tabela original para as 5 tabelas novas?
    Se sim, você pode usar um simples INSERT INTO... SELECT ou até o Integration Services.

    Descreva mais o seu problema pra tentar te direcionar melhor.

    []'s

    Mariana


    Mariana Del Nero /* Se a resposta foi útil, não esqueça de marcá-la */

    segunda-feira, 4 de agosto de 2014 18:38
  • Sim Mariana,

    Dividir esta principal, porém em 5 partes iguais.

    segunda-feira, 4 de agosto de 2014 18:44
  • Sem nenhum critério? Quero dizer, sem nenhum filtro por campo(s)?

    Simplesmente pegar as 880.000 linhas e dividir em 5 partes?

    Exemplo:
    Tabela 1: registros de 0 a 176.000

    Tabela 2: registros de 176.000 a 352.000

    Tabela 3: registros de 352.000 a 528.000

    Tabela 4: registros de 528.000 a 704.000

    Tabela 5: registros de 704.000 a 888.000


    Mariana Del Nero /* Se a resposta foi útil, não esqueça de marcá-la */

    segunda-feira, 4 de agosto de 2014 18:56
  • Exatamente, 

    Tenho um sistema de consultas que só processa 200mil registros por vez, desta forma preciso desta divisão.

    Peço desculpas se é uma questão boba, mas como sou novato, não sei como pesquisar.

    Obrigado!

    segunda-feira, 4 de agosto de 2014 18:59
  • Deleted
    segunda-feira, 4 de agosto de 2014 19:13
  • Olá Jose,

    Está é apenas uma tabela auxiliar, onde buscarei clientes para enriquecer uma informação e liberar para o call center ligar. Ninguém ou nehum sistema irá consultar esta tabela, apenas eu.

    Tenho campos cadastrais simples e se pudesse escolher a divisão faria por DDD para organizar. estes são meus campos.

    MTR
    NOME
    NASC
    CPF
    NOME
    ENDERECO
    NUMERO
    COMPL
    BAIRRO
    CEP
    CIDADE
    UF
    DDD
    FONE

    Abs

    segunda-feira, 4 de agosto de 2014 19:20
  • Pode ser via view também, pois de qualquer forma precisarei carregar a consulta através de um insert. 

    A questão é que não sei como dividir em partes iguais ... rs

    Abs

    segunda-feira, 4 de agosto de 2014 19:33
  • Boa tarde Carlos, o mais importante a saber inicialmente é qual versão do SQL Server que você utiliza, isso porque dependendo da versão você pode utilizar o recurso de tabelas particionadas.

    Espero ter ajudado

    segunda-feira, 4 de agosto de 2014 20:02
  • Oi Anderson, 

    Aqui é 2008 r2.

    Obrigado pela atenção!

    segunda-feira, 4 de agosto de 2014 20:06
  • Pessoal,

    Fui do modo mais básico mesmo, coloquei um Índice na tabela e gerei o insert into nas faixas que precisava dividir.

    Imagino que não seja o caminho ideal, mas atendeu minha questão.

    Obrigado e abraço a todos!


    segunda-feira, 4 de agosto de 2014 20:26
  • Carlos,

    Você pode dividir os dados de sua tabela utilizando os métodos "OFFSET" e "FETCH NEXT".

    Veja um exemplo para você adaptar às suas necessidades:

    --PARA OBTER OS 200.000 "PRIMEIROS REGISTROS" SELECT * FROM TB_EXEMPLO ORDER BY CD_DOC OFFSET 0 ROWS FETCH NEXT 200000 ROWS ONLY;
    GO --PARA OBTER OS REGISTROS 200.001 ATÉ 400.000 SELECT * FROM TB_EXEMPLO ORDER BY CD_DOC OFFSET 200000 ROWS FETCH NEXT 200000 ROWS ONLY;
    GO

    Você poderá utilizar a divisão conforme a Mariana indicou ou como você especificou (limitando à 200 mil registros).

    O artigo abaixo indica exemplos de paginação com T-SQL, que também podem ser úteis neste caso:

    http://social.technet.microsoft.com/wiki/pt-br/contents/articles/23533.paginando-uma-consulta-com-sql-server.aspx

    Para maiores informações veja:

    http://technet.microsoft.com/pt-br/library/ms188385.aspx#Offset


    Se ajudou na sua solução, não esqueça de marcar como resposta !

    Abraços,

    Durval Ramos
    Microsoft Partner | MTA | MCSA - SQL Server 2012 | MCSE - Data Platform
    ----------------------------------
    Se foi resolvido clique "Marcar como resposta" e se foi útil "Votar como Útil"
    terça-feira, 5 de agosto de 2014 12:04
    Moderador
  • Carlos,

    Desenvolvi um script para tentar te ajudar. 

    Se estivesse no SQL Server 2012 a cláusula OFFSET como indicado pelo Durval seria perfeita, mas como você está no 2008, terá que usar o ROW_NUMBER() mesmo.

    O código abaixo divide sua tabela original em N outras tabelas de acordo com o numero que você especificar (fiz assim caso sua tabela fique maior que os 880 mil registros).

    Fiz o ranking por DDD, mas nada impede que um DDD fique em duas ou mais tabelas, já que você está dividindo em blocos de 200.000

    Substitua abaixo o nome da sua tabela que chamei de "TABELAORIGINAL" e também a lista de campos onde marquei como comentário.
    No script chamei as tabelas que receberão os dados de Tabela1, tabela2 e assim por diante.

    Deixei o comando de execução do INSERT (EXEC(@Comando)) comentado. Basta descomentá-lo após os ajustes.

    SET NOCOUNT ON
    GO
    
    
    CREATE TABLE #TMP
    (
    	NumLinha INT,
    	TabelaDestino Int,
    	-- COLOCAR AQUI A LISTA DE CAMPOS E TIPOS IGUAIS A SUA TABELA ORIGINAL
    )
    
    
    INSERT INTO #tmp
    SELECT ROW_NUMBER() OVER (ORDER BY DDD),  NULL 
    -- COLOCAR AQUI A LISTA DE CAMPOS DA SUA TABELA ORIGINAL
    FROM TabelaOriginal --SUBSTITUIR PELO NOME DA SUA TABELA ORIGINAL
    
    
    
    DECLARE @QtdeRegistros INT
    SET @QtdeRegistros = (SELECT MAX(NumLinha) FROM #TMP)
    DECLARE @NumTabelas FLOAT
    SET @NumTabelas = 2
    
    
    WHILE 1=1
    BEGIN
    
    	IF (SELECT CONVERT(FLOAT, @QtdeRegistros/@NumTabelas)) > 200000 -- NUMERO MÁXIMO DE REGISTROS QUE VOCÊ DESEJA POR TABELA
    	BEGIN
    		SET @NumTabelas = @NumTabelas + 1
    	END
    	ELSE
    	BEGIN
    		BREAK
    	END
    
    END
    
    
    DECLARE @Contador INT = 1
    DECLARE @Contador1 INT = 1
    
    
    WHILE (@Contador <= @QtdeRegistros)
    BEGIN
    
    	UPDATE #TMP
    	SET TabelaDestino = @Contador1
    	WHERE NumLinha >= @contador
    	AND NumLinha < @contador + 2
    
    	SET @Contador = @CONTADOR + 2
    	SET @Contador1 = @Contador1 + 1
    
    
    
    END
    
    
    DECLARE @Comando NVARCHAR(MAX)
    SET @Contador = 1
    
    WHILE (@Contador <= @NumTabelas)
    BEGIN
    
    	SET @Comando = N'INSERT INTO TABELA' + CONVERT(VARCHAR(3), @Contador) 
    	+ ' (LISTA DE CAMPOS DA SUA TABELA ORIGINAL)
    		SELECT LISTA DE CAMPOS DA SUA TABELA ORIGINAL
    		FROM #TMP
    		WHERE TABELADESTINO = ' + CONVERT(VARCHAR(3), @Contador) 
    
    	PRINT @COMANDO
    	--EXEC(@COMANDO) 
    
    	SET @Contador = @Contador + 1
    
    
    END
    
    
    
    DROP TABLE #TMP


    Espero ter ajudado...


    Mariana Del Nero /* Se a resposta foi útil, não esqueça de marcá-la */

    terça-feira, 5 de agosto de 2014 13:02
  • Deleted
    terça-feira, 5 de agosto de 2014 13:27
  • Mariana,

    Testei aqui e funcionou perfeitamente.

    Agradeço muito a atenção e a lição.

    Abs

    quarta-feira, 6 de agosto de 2014 18:51
  • José,

    Também testei aqui e foi como eu precisava.

    Mito obrigado pela atenção e por seu empenho!

    Abs

    quarta-feira, 6 de agosto de 2014 18:52