Migração do MySQL pro SQL Server - dúvida

Fórum sobre Banco de Dados e RDDs para Clipper/[x]Harbour.

Moderador: Moderadores

cjp
Usuário Nível 6
Usuário Nível 6
Mensagens: 1563
Registrado em: 19 Nov 2010 22:29
Localização: paraná
Contato:

Migração do MySQL pro SQL Server - dúvida

Mensagem por cjp »

Pessoal, em razão de uma necessidade interna, estou mudando parte do meu banco de dados do MySQL para o SQL Server.
Já me deparei com várias alterações a serem feitas, as quais vou pesquisando e resolvendo.
Mas tem uma que não consegui solução. Alguém poderia me ajudar?

A questão é a seguinte: como exemplo, esta é uma query que eu executo sem problema no MySQL:

Código: Selecionar todos

SELECT nrtarefa,assunto,prioridade,data,hora,tarefa FROM tarefas WHERE prioridade>0 AND soluc='N' AND (exibe='N' OR exibe='I') AND (now())>=hrexibe AND vinculo<>'MP' AND data>='"+dtsql(dtapart)+"' GROUP BY nrtarefa ORDER BY prioridade DESC,data,nrtarefa
No SQL Server, mesmo trocando o now() por getdate(), esta query dá o seguinte erro SQL (8120): A coluna tarefas.ASSUNTO é inválida na lista de seleção porque não está contida em uma função de agregação nem na cláusula GROUP BY.

Pesquisando na internet, as informações são de que, no SQL Server, todas as colunas do select têm que estar no GROUP BY. E, de fato, colocando assim, não dá erro.

Mas o problema é que, assim, a consulta não fica como pretendia. A ideia do GROUP BY nrtarefa é que apareça apenas uma vez cada grupo de registros com o mesmo nrtarefa. Mas preciso passar para o browse todos os campos que estão no select.

Alguém poderia me ajudar nesta questão, por favor?
Inacio de Carvalho Neto
marco.prodata
Usuário Nível 3
Usuário Nível 3
Mensagens: 238
Registrado em: 30 Nov 2018 10:07
Localização: Caratinga

Migração do MySQL pro SQL Server - dúvida

Mensagem por marco.prodata »

Estranho é essa query funcionar no Mysql, group by é pra ser usado com funções de agregação (sum, avg, etc), e todos os outros campos que não vão ser agregados, devem estar dentro do group by, se vc quiser apenas uma ocorrencia de um campo, nesse caso vc vai ter que usar o distinct. Uma dúvida nesta tabela existe a possibilidade de ter 2 registros com o mesmo nrtarefa, e algum desses outros campos diferentes (assunto, prioridade, data, hora, tarefa) ?
cjp
Usuário Nível 6
Usuário Nível 6
Mensagens: 1563
Registrado em: 19 Nov 2010 22:29
Localização: paraná
Contato:

Migração do MySQL pro SQL Server - dúvida

Mensagem por cjp »

Funciona no MySQL sim.
Sim, tem vários registros com o mesmo nrtarefa, assim como os demais campos citados. A tabela tem um campo id que é único.
Testei agora com distinct, mas não resolveu, ainda não está selecionando só um de cada nrtarefa. Veja se fiz algo errado, por favor:

Código: Selecionar todos

SELECT distinct nrtarefa,assunto,prioridade,data,hora,tarefa FROM tarefas WHERE prioridade>0 AND soluc='N' AND (exibe='N' OR exibe='I') AND (getdate())>=hrexibe AND vinculo<>'MP' AND data>='2023-11-01' ORDER BY prioridade DESC,data,nrtarefa
Inacio de Carvalho Neto
alxsts
Colaborador
Colaborador
Mensagens: 3092
Registrado em: 12 Ago 2008 15:50
Localização: São Paulo-SP-Brasil

Migração do MySQL pro SQL Server - dúvida

Mensagem por alxsts »

Olá!

Não li a tua query ainda mas, tenha em mente o seguinte:
WHERE seleciona linhas.
HAVING seleciona grupos de linhas agrupadas com GROUP BY.

Use HAVING...
[]´s
Alexandre Santos (AlxSts)
cjp
Usuário Nível 6
Usuário Nível 6
Mensagens: 1563
Registrado em: 19 Nov 2010 22:29
Localização: paraná
Contato:

Migração do MySQL pro SQL Server - dúvida

Mensagem por cjp »

Entendo.
Mas não é isso que estou fazendo?
O Group by vai apenas agrupar as linhas selecionadas, exibindo apenas uma de cada nrtarefa.
O Having se aplicaria a este caso?
Inacio de Carvalho Neto
alxsts
Colaborador
Colaborador
Mensagens: 3092
Registrado em: 12 Ago 2008 15:50
Localização: São Paulo-SP-Brasil

Migração do MySQL pro SQL Server - dúvida

Mensagem por alxsts »

Olá!

Depois de ler a tua query, vi que não é caso para HAVING e sim para DISTINCT.

Pelo que já vi em outros posts teus, o campo hora das tuas tabelas é string no formato "HH:MM". Assim, esta comparação de hora que está fazendo não vai funcionar. Now() é do MySQL. No SQL Server é Getdate(), que retorna um timestamp com data, hora e fração de segundos. Para comparar esta hora, vai precisar extrair a hora retornada por Getdate():

Código: Selecionar todos

LEFT( CONVERT(Char(5), GETDATE(), 108), 5 )
Provavelmente isto está influenciando no retorno da consulta.
cjp escreveu:estou mudando parte do meu banco de dados
Estranho isto... ou muda tudo ou não muda nada...
[]´s
Alexandre Santos (AlxSts)
alxsts
Colaborador
Colaborador
Mensagens: 3092
Registrado em: 12 Ago 2008 15:50
Localização: São Paulo-SP-Brasil

Migração do MySQL pro SQL Server - dúvida

Mensagem por alxsts »

Ola!

Complementando: revise sua função dtsql(). Deve usar a função Getdate() e extrair a data do que ela retorna.

Código: Selecionar todos

CONVERT(Char(10), GETDATE(), 103)
[]´s
Alexandre Santos (AlxSts)
cjp
Usuário Nível 6
Usuário Nível 6
Mensagens: 1563
Registrado em: 19 Nov 2010 22:29
Localização: paraná
Contato:

Migração do MySQL pro SQL Server - dúvida

Mensagem por cjp »

Não sei se te entendi bem. Não estou usando a minha dtsql() neste caso.
Sei que o SQL Server não usa a now(). Já troquei pela getdate().
Sim, meu campo hora é caracter, no estilo "HH:MM". Já o campo hrexibe é datetime.
Mas, salvo engano meu, isto não influi na questão deste post. O select está retornando corretamente os registros corretamente. A questão é apenas o agrupamento, que eu fazia com o GROUP BY, e que não está funcionando no SQL Server, nem com GROUP BY nem com o DISTINCT.
Detalhe: estou mudando parte do banco para o SQL Server, e não todo ele, por dois motivos: 1) só algumas tabelas é que vou usar em um local que não tem acesso ao MySQL; então, só preciso realmente mudar essas tabelas; 2) o custo do SQL Server inviabilizaria a mudança de todo o banco, que é muito grande. Mas estou tratando disso com cuidado. A parte que vai usar o SQL Server com os comandos próprios do SQL Server, sem alterar o que já estava funcionando no MySQL e que continuará funcionando.
Inacio de Carvalho Neto
marco.prodata
Usuário Nível 3
Usuário Nível 3
Mensagens: 238
Registrado em: 30 Nov 2018 10:07
Localização: Caratinga

Migração do MySQL pro SQL Server - dúvida

Mensagem por marco.prodata »

cjp escreveu:Funciona no MySQL sim.
Sim, tem vários registros com o mesmo nrtarefa, assim como os demais campos citados. A tabela tem um campo id que é único.
Testei agora com distinct, mas não resolveu, ainda não está selecionando só um de cada nrtarefa. Veja se fiz algo errado, por favor:

Código: Selecionar todos

SELECT distinct nrtarefa,assunto,prioridade,data,hora,tarefa FROM tarefas WHERE prioridade>0 AND soluc='N' AND (exibe='N' OR exibe='I') AND (getdate())>=hrexibe AND vinculo<>'MP' AND data>='2023-11-01' ORDER BY prioridade DESC,data,nrtarefa
Não conheço a sintaxe do MS SQL SERVER, mas no postgresql seria assim:
select distinct on (nrtarefa) nrtarefa, assunto, prioridade ....
no distinct on vc passa quais campos ele vai filtrar, e depois vc passa quais campos quer de retorno, ali vc tá passando todos os campos, então ele usar todos pra fazer a filtragem, eu vi um exemplo aqui, não sei se do ms sql server assim select distinct(nrtarefa), assunto, prioridade, algo assim, que ali fala que o distinct vai ser apenas no campo nrtarefa, faça esse teste.
cjp
Usuário Nível 6
Usuário Nível 6
Mensagens: 1563
Registrado em: 19 Nov 2010 22:29
Localização: paraná
Contato:

Migração do MySQL pro SQL Server - dúvida

Mensagem por cjp »

select distinct on dá erro no SQL Server.
Com select distinct apenas, não dá erro, mas não funciona como esperado.
Veja esta query:

Código: Selecionar todos

SELECT distinct nrtarefa,assunto,prioridade,data,hora,tarefa FROM tarefas WHERE prioridade>0 AND soluc='N' AND (exibe='N' OR exibe='I') AND (getdate())>=hrexibe AND vinculo<>'MP' AND data>='2023-11-01' ORDER BY prioridade DESC,data,nrtarefa
Veja o resultado no anexo. Está aparecendo mais de um registro do mesmo nrtarefa.

Se eu colocar apenas select distinct nrtarefas from tarefas... (o que não me serviria, pois preciso dos demais campos no select), ele dá erro SQL (145): Itens Order by devem aparecer na lista de seleção se select distinct for especificado.

Se eu colocar order by nrtarefas apenas, não dá erro. Mas assim a consulta não fica como preciso.
Anexos
tela.png
Inacio de Carvalho Neto
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Migração do MySQL pro SQL Server - dúvida

Mensagem por JoséQuintas »

Sei lá...
Já falei pra organizar as bases de dados há anos.
tenta virtualmente

Código: Selecionar todos

select campos
from
where id in
( select nrtarefa, max(id) from .. group by nrtarefa )
and
Vai pegar a id da informação mais recente, e aplicar filtro nisso.
ou cria view já que vai usar muito.

Sei lá se isso vai ser eficiente.
Saiba que está sobrecarregando cada vez mais o servidor.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
marco.prodata
Usuário Nível 3
Usuário Nível 3
Mensagens: 238
Registrado em: 30 Nov 2018 10:07
Localização: Caratinga

Migração do MySQL pro SQL Server - dúvida

Mensagem por marco.prodata »

cjp escreveu:select distinct on dá erro no SQL Server.
Com select distinct apenas, não dá erro, mas não funciona como esperado.
Veja esta query:

Código: Selecionar todos

SELECT distinct nrtarefa,assunto,prioridade,data,hora,tarefa FROM tarefas WHERE prioridade>0 AND soluc='N' AND (exibe='N' OR exibe='I') AND (getdate())>=hrexibe AND vinculo<>'MP' AND data>='2023-11-01' ORDER BY prioridade DESC,data,nrtarefa
Veja o resultado no anexo. Está aparecendo mais de um registro do mesmo nrtarefa.

Se eu colocar apenas select distinct nrtarefas from tarefas... (o que não me serviria, pois preciso dos demais campos no select), ele dá erro SQL (145): Itens Order by devem aparecer na lista de seleção se select distinct for especificado.

Se eu colocar order by nrtarefas apenas, não dá erro. Mas assim a consulta não fica como preciso.
Vc tentou colocar apenas o campo que quer entre parentese?

select distinct(nrtarefas), campo2, campo3, campo4, etc, from ...
cjp
Usuário Nível 6
Usuário Nível 6
Mensagens: 1563
Registrado em: 19 Nov 2010 22:29
Localização: paraná
Contato:

Migração do MySQL pro SQL Server - dúvida

Mensagem por cjp »

Vc tentou colocar apenas o campo que quer entre parentese?

select distinct(nrtarefas), campo2, campo3, campo4, etc, from ...
Tentei sim, não funciona.
Vai pegar a id da informação mais recente, e aplicar filtro nisso.
Tentei fazer isso, mas não consegui. Consegue me dar um exemplo para eu entender melhor como seria, por favor?


ou cria view já que vai usar muito.
Desculpe, mas não entendi. O que seria criar view?


Saiba que está sobrecarregando cada vez mais o servidor.
Vc quer dizer que a consulta vai ficar lenta?
Inacio de Carvalho Neto
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Migração do MySQL pro SQL Server - dúvida

Mensagem por JoséQuintas »

O servidor faz o trabalho que quiser, dependendo do trabalho, toma mais tempo/recursos do servidor.
Num servidor de internet, eles enviam aviso sobre isso, e podem ou não impedir o uso se estiver atrapalhando outros usuários.

é um comando misto, nem chega a ser sub-query, que também existe.

É só pensar em partes:
Como selecionar determinadas tarefas:

Código: Selecionar todos

SELECT NRTAREFA, NOME FROM TABELA WHERE IDTAREFA IN ( 1, 2, 3, 4, 5 )
Não sei se vai deixar sem indicar nrtarefa, mas se obrigar a colocar, o retorno não vai ser mais uma lista simples:
Como saber o último lançamento ? seria a ID com número maior..

Código: Selecionar todos

SELECT MAX( IDTAREFA ) FROM TAREFAS GROUP BY NRTAREFA
Como usar um pra facilitar o outro?

Código: Selecionar todos

SELECT NRTAREFA, DESCRICAO
WHERE IDTAREFA IN
( o comando que pega lista )
Não sei se inner join facilitaria ou não nesse caso
No SQL Server não sei, mas no MySQL:

Código: Selecionar todos

SELECT A.NRTAREFA, A.DESCRICAO
   FROM TABELA AS A
INNER JOIN
( SELECT NRTAREFA, MAX(IDTAREFA) AS ID FROM TABELA ) AS B
ON A.IDTAREFA = B.ID
WHERE filtro
Veja o que é aceito.

E sobre as datas, resolveu ?
Se tiver que atualizar ODBC do SQL SERVER vai voltar à mesma situação anterior, de não poder instalar nada, e só está perdendo tempo seu e dos outros.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
marco.prodata
Usuário Nível 3
Usuário Nível 3
Mensagens: 238
Registrado em: 30 Nov 2018 10:07
Localização: Caratinga

Migração do MySQL pro SQL Server - dúvida

Mensagem por marco.prodata »

Pesquisando um pouco a respeito, parece que no MS SQL SERVER tanto o group by, quanto o distinct só funcionam na linha inteira, diferentemente do postgresql, que a opção de usar o distinct em campos especificos da query, abaixo segue um exemplo que talvez te ajude a resolver o problema.

Código: Selecionar todos

WITH CTE AS
(
SELECT ID, 
       Email, 
       ProductName, 
       ProductModel, 
       ROW_NUMBER() OVER (PARTITION BY Email ORDER BY ID DESC) AS RowNumber 
FROM   Products
)
SELECT ID, 
       Email, 
       ProductName, 
       ProductModel
FROM CTE 
WHERE RowNumber = 1
Responder