Temos uma política bastante restritiva em relação a anúncios no site. Eles nunca irão te atrapalhar! Além disso, usamos banners para lhe informar de assuntos importantes. Os bloqueadores de anúncios impedem que esses banners sejam visualizados. Sendo assim, para continuar, é importante que você desligue o bloqueador de anúncio e recarregue a página. Obrigado!
PHP 8.4 lançado com várias melhorias para versões modernas do Firebird: Esta atualização traz melhorias importantes para o driver PDO-Firebird integrado. Agora, com suporte a tipos de dados modernos, incluindo o DECFLOAT, o driver oferece benefícios significativos para aplicações PHP que utilizam Firebird 4 e 5.
Mudanças relacionadas ao PDO-Firebird no Changelog do PHP:
Corrigido o comportamento dos métodos `setAttribute` e `getAttribute`.
Novo recurso**: Adicionadas configurações de nível de isolamento e modo de transação ao `pdo_firebird`.
Adicionada a classe `Pdo\Firebird`.
Adicionado `Pdo\Firebird::ATTR_API_VERSION`.
Adicionado `getApiVersion()` (removido do `getAttribute()`).
Suporte aos tipos de dados do Firebird 4.0 (GH-14896).
Suporte à formatação correta para tipos de fuso horário.
Corrigido GH-15604 (Sempre tornar os parâmetros de entrada anuláveis).
A partir da versão 3 do Firebird, a implementação de Window Functions (funções de janela) trouxe ao banco de dados um conjunto de ferramentas avançadas para análise de dados e cálculos agregados sem a necessidade de subconsultas complexas. Com o lançamento de novas versões, essas funcionalidades permanecem e são refinadas, proporcionando aos desenvolvedores e DBAs uma forma mais expressiva, legível e eficiente de construir relatórios, análises gerenciais e estatísticas dentro do próprio SQL.
Neste artigo, detalharemos as principais window functions suportadas pelo Firebird 5, explicando o que são, como funcionam e apresentando exemplos práticos de uso. Além disso, mostraremos como elas podem ser aplicadas em um contexto de ERP (Enterprise Resource Planning), onde relatórios de vendas, controles financeiros e análises de desempenho costumam fazer parte da rotina.
O que são Window Functions?
Window functions são funções que permitem realizar cálculos agregados (como somas, contagens, médias) ou análises baseadas em ranking e ordenação, sem que seja necessário reduzir o conjunto de resultados a uma única linha. Ao contrário das funções de agregação tradicionais (SUM, AVG, COUNT, etc.) utilizadas com GROUP BY, as window functions permitem exibir resultados parciais ao lado do detalhamento original.
Elas operam sobre uma "janela" (window) definida sobre o conjunto de linhas retornadas pela cláusula FROM (após filtros e junções). Essa janela é definida usando a cláusula OVER, que pode incluir:
PARTITION BY: Segmenta o conjunto de resultados em grupos (partições) sobre os quais a função irá atuar.
ORDER BY: Determina a ordem das linhas dentro de cada partição, fundamental para funções de ranking e funções que dependem da posição dos registros.
Frame Clauses (opcional): Permitem refinar ainda mais o conjunto de linhas consideradas pela função em relação à linha corrente (por exemplo, considerar somente as últimas 3 linhas anteriores, ou um período entre duas datas).
Tipos de Window Functions Disponíveis
O Firebird 5 oferece um conjunto significativo de window functions, divididas basicamente em três categorias:
Funções de Agregação aplicadas como Window Functions
As mesmas funções de agregação tradicionais podem ser usadas como window functions, por exemplo: SUM(), AVG(), COUNT(), MIN(), MAX(), VAR_POP(), VAR_SAMP(), STDDEV_POP(), STDDEV_SAMP().
Funções de Ranking
ROW_NUMBER(): Numera as linhas sequencialmente dentro da partição, começando em 1.
RANK(): Atribui uma posição à linha dentro da partição com base na ordem, mas permite empates. Linhas com o mesmo valor de ordenação recebem o mesmo rank, e o próximo valor de rank é incrementado pelo número de empates.
DENSE_RANK(): Similar ao RANK(), mas sem pular valores no caso de empates. Se duas linhas recebem rank 1, a próxima linha recebe rank 2, e não 3.
Funções de Acesso a Valores (Value Functions)
FIRST_VALUE(expr): Retorna o primeiro valor de expr na janela definida.
LAST_VALUE(expr): Retorna o último valor de expr na janela definida.
LAG(expr, [offset], [default]): Acessa o valor da linha anterior na janela, considerando um offset (por padrão, 1 linha atrás).
LEAD(expr, [offset], [default]): Acessa o valor de uma linha subsequente na janela, considerando um offset (por padrão, 1 linha à frente).
NTH_VALUE(expr, n): Retorna o valor da expressão na n-ésima posição da janela.
Como Funcionam?
As window functions são adicionadas ao SELECT e usam a cláusula OVER(). Dentro do OVER(), podemos especificar como as linhas serão particionadas e ordenadas. Exemplo simples:
select N.REPRESENTANTE,
N.EMISSAO,
N.VALOR_NOTA,
sum(N.VALOR_NOTA) over(partition by N.REPRESENTANTE order by N.EMISSAO) as ACUMULADO_VENDEDOR
from NOTAS N
where N.TIPOOPER = 2 /* Vendas */ and
N.EMISSAO between date '1.1.2010' and date '31.01.2010'
No exemplo acima, SUM(N.VALOR_NOTA) é calculado de forma cumulativa (de acordo com o ORDER BY N.EMISSAO) para cada vendedor (PARTITION BY N.REPRESENTANTE):
Detalhando Cada Função e Exemplos Práticos em um ERP
A seguir, detalharemos cada função, mostrando como podem ser utilizadas em um ambiente de ERP típico, onde temos tabelas como: notas, produtoas das notas, clientes, fornecedores, estoque, etc.
1. Funções de Agregação como Window Functions
SUM(): Retorna a soma dos valores sobre a janela definida. Exemplo ERP: Calcular o total de vendas acumuladas por mês para cada vendedor.
select N.REPRESENTANTE,
extract(year from N.EMISSAO) as ANO,
extract(month from N.EMISSAO) as MES,
N.VALOR_NOTA,
sum(N.VALOR_NOTA) over(partition by N.REPRESENTANTE, extract(year from N.EMISSAO), extract(month from N.EMISSAO)) as TOTAL_MENSAL
from NOTAS N
where N.TIPOOPER = 2 and
N.EMISSAO between date '1.1.2010' and date '31.12.2010'
Aqui obtemos, ao lado de cada venda, o total mensal de vendas do vendedor naquele ano e mês, sem precisar de subconsultas.
AVG(): Calcula a média dos valores na janela. Exemplo ERP: Média móvel de vendas dos últimos 3 meses por produto.
select PN.CODPROD,
N.REFERENTE as ANO_MES,
sum(PN.SUBTOTAL) as VALOR_MES,
avg(sum(PN.SUBTOTAL)) over (partition by PN.CODPROD
order by N.REFERENTE
rows between 2 preceding and current row) as MEDIA_MOVEL_3_MESES
from NOTAS N
join PRODNOTA PN on PN.ID_NUM = N.ID_NUM
where N.TIPOOPER = 2 /* Vendas */ and
N.EMISSAO between date '1.1.2010' and date '31.12.2010'
group by PN.CODPROD, N.REFERENTE
Neste exemplo, primeiro agregamos o total mensal de vendas por produto. Depois, aplicamos uma média sobre uma janela de 3 períodos (o mês atual e os dois meses anteriores), criando uma média móvel. A coluna REFERENTE é do tipo DATE e armazena o primeiro dia (01) do mês e do ano da data de emissão da NF.
COUNT(): Conta o número de linhas na janela. Exemplo ERP: Quantidade acumulada de itens vendidos por cliente em todo o histórico.
select N.CLIFORN as CODCLI,
N.EMISSAO as DATA_VENDA,
count(*) over(partition by N.CLIFORN order by N.EMISSAO) as CONTAGEM_ACUMULADA_VENDAS
from NOTAS N
where N.TIPOOPER = 2 /* Vendas */ and
N.EMISSAO between date '1.1.2010' and '31.12.2010'
order by 1, 2
Resultado:
Observe que há linhas duplicadas no resultado. Quando utilizamos funções janela, é importante lembrar que elas não agrupam ou consolidam as linhas como o GROUP BY faz. Em outras palavras, a função janela adiciona uma coluna calculada a cada linha retornada pela consulta, mas não reduz o número de linhas. Cada linha original da tabela continua sendo exibida no resultado final.
O que ocorre é o seguinte:
PARTITION BY vendedor_id: Divide o conjunto de resultados em partições (grupos lógicos), uma para cada vendedor. ORDER BY data_venda: Dentro de cada partição, as linhas são ordenadas pela data da venda. COUNT(*) OVER(...): Aplica a contagem cumulativa sobre as linhas já ordenadas, de modo que cada linha exibe o total de linhas até aquela posição na ordem definida.
Se você tiver, por exemplo, várias vendas para o mesmo cliente na mesma data, cada uma dessas vendas aparecerá como uma linha distinta no resultado, pois elas representam registros diferentes na tabela vendas. A função janela não "agrupará" essas linhas em um único registro. Por isso, como no exemplo acima, é perfeitamente possível ter várias linhas com o mesmo cliente, a mesma data e a mesma contagem acumulada. O resultado é "duplicado" no sentido visual, mas na realidade são linhas distintas da tabela base.
MIN()/MAX(): Retornam o valor mínimo ou máximo na janela. Exemplo ERP: Analisar o histórico de vendas de cada cliente, entender há quanto tempo ele está comprando conosco, e quantos dias se passaram desde sua primeira compra..
select N.CLIFORN,
N.EMISSAO,
N.VALOR_NOTA,
min(N.EMISSAO) over(partition by N.CLIFORN) as PRIMEIRA_COMPRA,
max(N.EMISSAO) over(partition by N.CLIFORN) as ULTIMA_COMPRA,
datediff(day from min(N.EMISSAO) over(partition by N.CLIFORN) to N.EMISSAO) as DIAS_DESDE_PRIMEIRA_COMPRA
from NOTAS N
where N.TIPOOPER = 2 /* Vendas */ and
N.EMISSAO between date '1.1.2010' and '31.12.2010' -- No exemplo, estamos limitando apenas as vendas de 2010
Resultado:
VAR_POP(), VAR_SAMP(), STDDEV_POP(), STDDEV_SAMP(): Fornecem variância e desvio padrão. Exemplo ERP: Avaliar a volatilidade do valor das vendas de um cliente dentro de um período (1 ano).
with VENDAS_DIARIAS
as (select N.EMISSAO as DIA,
extract(month from N.EMISSAO) as MES,
sum(N.VALOR_NOTA) as TOTAL_DIA
from NOTAS N
where N.CLIFORN = 9 and -- Cliente 9
N.TIPOOPER = 2 and -- Somente Vendas
N.EMISSAO between date '1.1.2010' and date '31.12.2010' -- Ano de 2010
group by 1, 2)
select DIA,
MES,
TOTAL_DIA,
stddev_samp(TOTAL_DIA) over(partition by MES) as DESVIO_PADRAO_MES, -- Desvio padrão amostral das vendas diárias dentro do mês
var_samp(TOTAL_DIA) over(partition by MES) as VARIANCIA_MES -- Variância amostral das vendas diárias dentro do mês
from VENDAS_DIARIAS
order by MES, DIA;
Resultado:
As funções estatísticas VAR_POP(), VAR_SAMP(), STDDEV_POP() e STDDEV_SAMP() fornecem medidas de dispersão dos dados dentro de uma janela definida. Elas ajudam a entender o quão espalhados ou voláteis os valores estão ao redor da média. A interpretação dessas métricas é particularmente útil em análises de desempenho, análises financeiras, controle de qualidade e outros contextos onde é importante compreender a variabilidade dos resultados.
Diferenças entre POP e SAMP:
VAR_POP() e STDDEV_POP(): Consideram que o conjunto de dados representa uma população inteira. Isso significa que você está analisando todos os dados relevantes e não faz inferências sobre um conjunto maior. Nesse caso, a fórmula da variância e do desvio padrão não ajusta o denominador (usa N, o tamanho total da população).
VAR_SAMP() e STDDEV_SAMP(): Consideram que o conjunto de dados é uma amostra de uma população maior. Por conta disso, aplicam o conceito de “amostra imparcial”, ajustando o denominador (usa N-1 em vez de N ao calcular a variância). Isso tende a gerar valores um pouco maiores, evitando subestimar a variabilidade real da população.
O que cada métrica significa:
Variância (VAR_POP, VAR_SAMP):
A variância mede o grau de dispersão dos valores em relação à média.
Quanto maior a variância, mais espalhados estão os dados.
Valores próximos à média geram uma variância menor; valores mais distantes aumentam a variância.
Entretanto, por ser expressa em "unidades ao quadrado" (por exemplo, se o dado é em reais, a variância será em reais²), sua interpretação direta não é tão intuitiva. Normalmente, a variância é mais útil como passo intermediário para o desvio padrão.
Desvio Padrão (STDDEV_POP, STDDEV_SAMP):
O desvio padrão é a raiz quadrada da variância, trazendo a métrica de volta à mesma unidade dos dados originais. Isso facilita a interpretação:
Um desvio padrão alto significa que os valores variam muito em relação à média.
Um desvio padrão baixo significa que a maioria dos valores está próxima da média.
Por exemplo, em um contexto de vendas diárias:
Um desvio padrão alto das vendas diárias significa que há dias de vendas muito altas e dias de vendas muito baixas, ou seja, uma grande volatilidade.
Um desvio padrão baixo indica que as vendas diárias são mais consistentes, oscilando pouco em torno da média.
Como interpretar o resultado:
total_dia: Valor total vendido para aquele cliente em um dia específico.
desvio_padrao_mes (STDDEV_SAMP): Indica o quão dispersas estão as vendas diárias dentro daquele mês.
Se o desvio padrão for baixo (próximo de zero), significa que, naquele mês, as vendas diárias foram relativamente consistentes (sem grandes picos ou vales).
Se for alto, significa que houve bastante variação: alguns dias muito bons, outros dias muito ruins, sugerindo falta de padrão ou estabilidade.
variancia_mes (VAR_SAMP): Parecida com o desvio padrão, mas ao quadrado. Não é tão intuitiva quanto o desvio padrão, mas serve como referência quantitativa da dispersão.
Pontos de Atenção:
Ao examinar o resultado, um mês com alto desvio padrão e variância indica que as vendas daquele cliente foram muito irregulares no período. Essa irregularidade pode sinalizar:
Necessidade de rever a política de descontos.
Problemas de estoque ou logística que fazem alguns dias terem vendas baixas e outros muito altas.
Campanhas de marketing não uniformes.
Mudanças no comportamento do cliente que merecem atenção, talvez com um contato pessoal para entender a variação.
Por outro lado, um mês com baixo desvio padrão mostra um padrão de compra mais estável, facilitando o planejamento e a previsão de demandas futuras.
Dessa forma, a análise de variância e desvio padrão por mês para um cliente específico ao longo do ano ajuda o gestor a identificar períodos problemáticos ou oportunos, permitindo ações mais direcionadas na estratégia comercial e operacional.
Diferença entre População e Amostra:
Se você está analisando todos os registros de vendas (por exemplo, todo o último ano, sem deixar nada de fora), usar STDDEV_POP() faz sentido, pois você está analisando a população completa de dados relevantes.
Já se você está analisando apenas um subconjunto de dias (por exemplo, 7 dias selecionados aleatoriamente) para inferir sobre um período maior, STDDEV_SAMP() pode ser mais apropriado, pois dá uma estimativa mais imparcial da variabilidade real da população.
Em resumo, o resultado dessas funções deve ser interpretado como indicadores do quão estáveis ou voláteis são os valores analisados. Elas ajudam a entender a “saúde estatística” dos dados, seja de vendas, custos, tempos de processo, ou qualquer outra métrica quantitativa que se deseja avaliar no ERP.
2. Funções de Ranking
ROW_NUMBER(): Gera uma numeração sequencial, sem repetições. Exemplo ERP: Enumerar as vendas de cada cliente na ordem cronológica dentro de um mês.
select row_number() over(partition by N.CLIFORN order by N.EMISSAO) as NUMERO_VENDA_CLIENTE,
N.CLIFORN,
N.EMISSAO,
N.VALOR_NOTA
from NOTAS N
where N.TIPOOPER = 2 /* Vendas */ and
N.EMISSAO between date '1.1.2010' and '31.1.2010'
Resultado:
RANK(): Atribui um ranking com possíveis “buracos” por empates. Exemplo ERP: Determinar a posição de cada vendedor no ranking mensal de vendas, considerando empates.
select rank() over(order by sum(N.VALOR_NOTA) desc) as POSICAO_NO_RANKING,
N.REPRESENTANTE,
sum(N.VALOR_NOTA) as TOTAL_MES
from NOTAS N
where N.TIPOOPER = 2 /* Vendas */ and
N.EMISSAO between date '1.1.2010' and '31.1.2010'
group by N.REPRESENTANTE
Resultado:
DENSE_RANK(): Similar ao RANK(), mas sem pular valores no caso de empates. Exemplo ERP: Ranking de produtos mais vendidos sem “espaços” quando há empates.
select dense_rank() over(order by sum(PN.SUBTOTAL) desc) as RANK_DENSE,
PN.CODPROD,
sum(PN.SUBTOTAL) as TOTAL_VENDIDO
from NOTAS N
join PRODNOTA PN on PN.ID_NUM = N.ID_NUM
where N.TIPOOPER = 2 /* Vendas */ and
N.EMISSAO between date '1.1.2010' and '31.12.2010'
group by PN.CODPROD
Resultado:
RANK(): Se houver um empate, por exemplo, dois produtos empatados em 1º lugar, ambos receberão RANK = 1. A linha seguinte, que ficaria em 3º lugar se contássemos normalmente, também será marcada como RANK = 3, pulando o número 2. Ou seja, cria-se um "espaço" no ranking após um empate.
DENSE_RANK(): No caso do mesmo empate de dois produtos na primeira posição, ambos recebem DENSE_RANK = 1. Porém, o próximo produto na sequência receberá DENSE_RANK = 2, sem pular o número 2, ou seja, sem deixar "espaços" na sequência da numeração.
3. Funções de Acesso a Valores
FIRST_VALUE(expr): Pega o primeiro valor da janela, de acordo com a ordenação. Exemplo ERP: Saber o primeiro preço de venda registrado para um produto, exibindo ao lado da venda atual.
select PN.CODPROD,
N.EMISSAO,
PN.PREC_UNIT,
first_value(PN.PREC_UNIT) over(partition by PN.CODPROD order by N.EMISSAO) as PRIMEIRO_PRECO_VENDA
from NOTAS N
join PRODNOTA PN on PN.ID_NUM = N.ID_NUM
where N.TIPOOPER = 2 /* Vendas */ and
N.EMISSAO between date '1.1.2010' and '31.12.2010'
Resultado:
LAST_VALUE(expr): Pega o último valor da janela. Exemplo ERP: Saber o último preço de venda anterior a uma determinada venda.
select PN.CODPROD,
N.EMISSAO,
PN.PREC_UNIT,
last_value(PN.PREC_UNIT) over(partition by
PN.CODPROD order by N.EMISSAO
rows between unbounded preceding and 1 preceding) as PRECO_ANTERIOR
from NOTAS N
join PRODNOTA PN on PN.ID_NUM = N.ID_NUM
where N.TIPOOPER = 2 /* Vendas */ and
N.EMISSAO between date '1.1.2010' and '31.12.2010'
Resultado:
LAG(expr, offset, default): Acessa valores de linhas anteriores. Exemplo ERP: Comparar o valor total de vendas de um produto com o total do mês anterior.
select PN.CODPROD,
N.REFERENTE as ANO_MES,
sum(PN.SUBTOTAL) as TOTAL_MES,
lag(sum(PN.SUBTOTAL), 1, 0) over(partition by PN.CODPROD order by N.REFERENTE) as TOTAL_MES_ANTERIOR
from NOTAS N
join PRODNOTA PN on PN.ID_NUM = N.ID_NUM
where N.TIPOOPER = 2 /* Vendas */ and
N.EMISSAO between date '1.1.2010' and '31.12.2010'
group by PN.CODPROD, N.REFERENTE
Resultado:
A função LAG() é uma função de janela que permite acessar o valor de uma coluna em uma linha anterior à linha atual, dentro da mesma partição e na ordem especificada. Ela é muito útil quando queremos comparar um registro atual com um anterior, sem precisar realizar auto-joins ou subconsultas complexas.
Como funciona? A sintaxe básica é:
LAG(expr, [offset], [default]) OVER (PARTITION BY ... ORDER BY ...)
expr: A expressão ou coluna cujo valor você quer recuperar de uma linha anterior. offset (opcional): Quantas linhas "para trás" você deseja olhar. Por padrão é 1, ou seja, a linha imediatamente anterior. default (opcional): Valor a ser retornado se não houver linha anterior suficiente (por exemplo, na primeira linha da partição não existe linha anterior). Se não for fornecido, o valor padrão é NULL.
A cláusula OVER define a janela, ou seja, como os dados são particionados e ordenados.
PARTITION BY: Separa os dados em grupos lógicos. Dentro de cada grupo, o LAG() só acessa linhas do mesmo grupo. ORDER BY: Define a ordem das linhas dentro da partição, determinando qual é a linha "anterior" ou "posterior".
LEAD(expr, offset, default): Acessa valores de linhas seguintes. Exemplo ERP: Mostrar o valor de uma venda para um cliente juntamente com o valor da próxima venda dele, para entender se os valores estão aumentando, diminuindo ou se há algum padrão.
select N.CLIFORN,
N.EMISSAO,
N.VALOR_NOTA,
lead(N.VALOR_NOTA, 1, null) over(partition by N.CLIFORN order by N.EMISSAO) as PROXIMA_VENDA_VALOR
from NOTAS N
where N.TIPOOPER = 2 /* Vendas */ and
N.EMISSAO between date '1.1.2010' and '31.12.2010'
Resultado:
A função LEAD() é uma função de janela similar à LAG(), mas em vez de retornar valores de linhas anteriores, ela retorna valores de linhas seguintes dentro da mesma partição. Ou seja, se LAG() permite "olhar para trás" no conjunto de resultados, LEAD() permite "olhar para a frente".
Sintaxe básica:
LEAD(expr, [offset], [default]) OVER (PARTITION BY ... ORDER BY ...)
expr: A expressão ou coluna cujo valor você deseja recuperar de uma linha futura. offset (opcional): Número de linhas "à frente" que você quer alcançar. Por padrão é 1, significando a próxima linha. default (opcional): Valor a ser retornado caso não exista uma linha seguinte o suficiente. Se omitido, retornará NULL quando não houver linha futura.
A cláusula OVER define a janela:
PARTITION BY: Separa as linhas em grupos lógicos. O LEAD() só buscará linhas futuras dentro do mesmo grupo. ORDER BY: Determina a ordem das linhas dentro da partição. A noção de "linha seguinte" depende desta ordenação.
NTH_VALUE(expr, n): Pega o n-ésimo valor da janela. Exemplo ERP: Obter a segunda venda mais cara de cada vendedor em um mês.
select N.REPRESENTANTE,
N.EMISSAO,
N.VALOR_NOTA,
nth_value(N.VALOR_NOTA, 2) over(partition by N.REPRESENTANTE order by N.VALOR_NOTA desc rows between unbounded preceding and unbounded following) as SEGUNDA_VENDA_MAIS_CARA
from NOTAS N
where N.TIPOOPER = 2 /* Vendas */ and
N.REFERENTE = date '1.1.2010'
Resultado:
A função de janela NTH_VALUE() permite recuperar o valor da n-ésima linha dentro da janela definida para cada grupo (partição) e ordem especificada. É parecida com FIRST_VALUE() e LAST_VALUE(), mas dá a flexibilidade de pegar não apenas o primeiro ou o último valor, mas qualquer posição específica dentro da partição.
Sintaxe:
NTH_VALUE(expr, n) OVER (PARTITION BY ... ORDER BY ... [frame_clause])
expr: A expressão ou coluna cujo valor se deseja obter. n: Um número inteiro que indica qual posição dentro da janela será retornada. Por exemplo, NTH_VALUE(expr, 2) retorna o segundo valor da partição considerando a ordem especificada.
OVER ( ... ): Define a janela sobre a qual a função opera.
PARTITION BY: Divide o conjunto de linhas em grupos lógicos. O NTH_VALUE só “enxerga” as linhas do mesmo grupo. ORDER BY: Determina a ordem das linhas dentro de cada partição. É a partir dessa ordem que se identifica qual é a primeira, segunda ou enésima linha. Frame Clause (opcional): Pode restringir ainda mais as linhas consideradas, definindo intervalos relativos à linha atual. Isso é importante, pois a posição “n” pode ser afetada se o frame não inclui todas as linhas da partição.
Como funciona? O NTH_VALUE() varre as linhas da partição na ordem estabelecida. A n-ésima linha nessa ordem determina qual valor será retornado para a função. Entretanto, a função considera o frame especificado. Se você não ajustar o frame, por padrão muitos bancos consideram a partição inteira como o frame, permitindo acesso a qualquer posição da mesma.
Conclusão
As window functions do Firebird 5 oferecem uma abordagem poderosa para análise de dados dentro do próprio banco, reduzindo complexidade de código, melhorando a performance em muitos casos e deixando as consultas mais expressivas. Ao definir janelas lógicas sobre o conjunto de resultados, essas funções permitem a criação de relatórios analíticos, rankings e cálculos cumulativos de maneira simples e eficiente.
Em um ERP, essas capacidades se traduzem diretamente em relatórios mais ricos, flexíveis e de fácil manutenção. Desde a análise de vendas por produto, cliente ou vendedor, passando por comparativos mensais, cálculo de médias móveis, identificação de top N produtos ou vendedores, até análises estatísticas mais avançadas, as window functions se tornaram uma ferramenta essencial no arsenal do desenvolvedor e do analista de dados.
Autor: Esse artigo foi uma experiência de geração de conteúdo com o ChatGPT o1. Todos os exemplos foram revisados e testados em um ERP real por Carlos H. Cantu.
Se você estiver usando uma versão do Firebird anterior a 3.0, a resposta é NÃO. O SYSDBA é um super usuário, ele pode tudo e mesmo que voce dê o máximo de direitos para outros usuários eles nunca poderão fazer as mesmas coisas que o SYSDBA pode.
Mas então como posso resolver o problema de que se alguém tiver acesso físico ao meu arquivo .GDB e copia-lo em outro computador onde a senha do SYSDBA seja conhecida, ele tem acesso à todas as minhas informações ?
Resposta: A segurança de um banco IB/FB está diretamente relacionada à segurança do sistema operacional usado no servidor de banco de dados. Voce deve usar um sistema operacional seguro (ex:Linux) e configura-lo de maneira que apenas usuários de alta confiabilidade tenham acesso físico aos arquivos .GDB bem como à qualquer arquivo de backup do banco. Lembre-se que para se acessar um banco de dados IB/FB por uma aplicação cliente não é necessário ter acesso físico ao banco.
E se eu estiver usando o servidor de BD no Windows 9x ou ME ?
Resposta: Essas versões do windows não fornecem a segurança necessária para voce barrar o acesso dos usuários aos GDBs e são desaconselhadas para se rodar um servidor de BD pois são muito instáveis. Troque para uma versão do Windows mais segura/estável (Windows 2000) ou use o Linux no servidor
Firebird 3
O Firebird 3 introduziu a API de criptografia, permitindo que você crie plugins para criptografar a base de dados a nível de páginas. Sendo assim, você pode impedir que um banco de dados roubado seja acessado em outro computador através do uso de um plugin de criptografia e garantindo que o ladrão não teve acesso a chave de criptografia utilizada e/ou ao plugin.
A IBSurgeon vende um plugin de criptografia para o Firebird 3. Você pode adquiri-lo por um preço especial através dos links especiais da FireBase em www.firebase.com.br/ibsurgeon.
Ferramenta de linha de comando destinada à migração e otimização de bancos de dados Firebird. Ele aborda aspectos da estrutura interna que o próprio mecanismo do Firebird não consegue corrigir, incluindo problemas que persistem mesmo após backup e restauração com o gbak. Além da otimização, o FBOpt permite atualizar ou reverter versões de bancos de dados entre diferentes versões do Firebird, converter bancos de dados para um novo conjunto de caracteres padrão e criar backups regulares com restauração simultânea.