AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 337681
Accepted
Viper75
Viper75
Asked: 2024-03-13 07:00:36 +0800 CST2024-03-13 07:00:36 +0800 CST 2024-03-13 07:00:36 +0800 CST

Como posso obter uma média de um conjunto de dados de consulta no SQL Server?

  • 772

Estou construindo um sistema de inventário de peças e tenho uma tabela de transações que armazena a frequência de uso de um item.
Digamos que o item A seja usado 10 vezes em 2021, 20 em 2022 e 30 em 2023. É claro que cada transação ocorre em um dia diferente ao longo de cada ano. Então, usando

SELECT ItemNumber, SUM(QuantityUsed), YEAR(DateUsed)
FROM ItemTransactions
GROUP BY ItemNumber, YEAR(DateUsed)
WHERE ItemNumber = 1001

Posso saber quantos foram usados ​​​​a cada ano. Minha pergunta é como posso obter o uso médio anual deste conjunto de dados? Tenho tentado usar uma subconsulta, mas não consegui fazê-la funcionar corretamente.

Obrigado!

sql-server
  • 3 3 respostas
  • 575 Views

3 respostas

  • Voted
  1. Andriy M
    2024-03-13T10:08:13+08:002024-03-13T10:08:13+08:00

    Existem várias maneiras de esfolar o gato aqui.

    1. Tabela derivada

    Use sua consulta como uma tabela e aplique agrupamento e agregação adicionais aos resultados:

    SELECT
      ItemNumber, AVG(QuantityUsed) AS AvgQuantityUsed
    FROM
      (
        SELECT
          ItemNumber, SUM(QuantityUsed) AS QuantityUsed
        FROM
          dbo.ItemTransactions
        WHERE
          ItemNumber = 1001
        GROUP BY
          ItemNumber, YEAR(DateUsed)
      ) AS derived
    GROUP BY
      ItemNumber
    ;
    

    2. CTE

    (Também sugerido na outra resposta .)

    Isto é basicamente o mesmo que a opção de tabela derivada, apenas o aninhamento é expresso usando uma sintaxe diferente:

    WITH
      derived AS
      (
        SELECT
          ItemNumber, SUM(QuantityUsed) AS QuantityUsed
        FROM
          dbo.ItemTransactions
        WHERE
          ItemNumber = 1001
        GROUP BY
          ItemNumber, YEAR(DateUsed)
      )
    SELECT
      ItemNumber, AVG(QuantityUsed) AS AvgQuantityUsed
    FROM
      derived
    GROUP BY
      ItemNumber
    ;
    

    Uma ligeira correção na consulta original que fiz nas duas opções acima é que deixei de fora YEAR(DateUsed)a cláusula SELECT por ser desnecessária para o cálculo da média. (No entanto, ele precisa permanecer no GROUP BY interno.)

    Aqui estão mais alguns que não envolvem aninhamento.

    3. Agregação de janelas + DISTINCT

    Você pode aplicar a versão da janela AVGdiretamente à SUMexpressão. O resultado serão as somas substituídas por médias idênticas por ItemNumbere você obterá um conjunto de linhas contendo várias duplicatas. Você pode suprimir as duplicatas apenas substituindo SELECT por SELECT DISTINCT:

    SELECT DISTINCT
      ItemNumber, AVG(SUM(QuantityUsed)) OVER (PARTITION BY ItemNumber) AS AvgQuantityUsed
    FROM
      dbo.ItemTransactions
    WHERE
      ItemNumber = 1001
    GROUP BY
      ItemNumber, YEAR(DateUsed)
    

    4. SOMA() / CONTAGEM(DISTINTO)

    Você também pode lembrar que a média anual de QuantityUsedper ItemNumberé essencialmente o total QuantityUsedper ItemNumberdividido pelo número total de anos distintos per ItemNumbere reescrever a consulta de acordo:

    SELECT
      ItemNumber, SUM(QuantityUsed) / COUNT(DISTINCT YEAR(DateUsed)) AS AvgQuantityUsed
    FROM
      dbo.ItemTransactions
    WHERE
      ItemNumber = 1001
    GROUP BY
      ItemNumber
    ;
    
    • 5
  2. Best Answer
    nbk
    2024-03-13T07:21:40+08:002024-03-13T07:21:40+08:00

    você pode usar um CTE para isso, o agrupamento por da seleção externa é útil se você precisar de informações em mais de um item

    WITH CTE as (
    SELECT ItemNumber, SUM(QuantityUsed) as QuantityUsed, YEAR(DateUsed)
    FROM ItemTransactions
    WHERE ItemNumber = 1001
    GROUP BY ItemNumber, YEAR(DateUsed)
    )
    SELECT ItemNumber, AVG(QuantityUsed) AS AVGQuantityUsed
    FROM CTE
    GROUP BY ItemNumber
    
    • 3
  3. Quassnoi
    2024-03-14T01:21:26+08:002024-03-14T01:21:26+08:00

    Todas as respostas postadas aqui até agora assumem que os anos em que o item não foi utilizado não devem contribuir para a média.

    Em outras palavras, se o uso anual for 10, 0, 10, a resposta que você obterá será 10 (não 6,66).

    Se você tiver itens listados no inventário em algum lugar, mas que não estão sendo usados ​​em transações, você não receberá nenhuma resposta para eles (em vez de obter o ID do item com um zero próximo a ele).

    Tudo isso pode ser realmente o que você deseja ou pode não ser um problema para o seu sistema, porque a maioria dos itens está sendo usada todos os anos desde que foram introduzidos e você não se importa com valores discrepantes ocasionais. Nesse caso, use qualquer uma das respostas acima.

    Se você deseja que todos os anos e todos os itens contribuam para a média, mesmo aqueles que não tiveram nenhuma movimentação, utilize uma das consultas abaixo.

    Anos fixos

    Esta consulta calcula a média do consumo anual de cada item do seu sistema durante um intervalo de tempo fixo. Como o sistema não sabe em que intervalo de tempo você deseja calcular a média (talvez você queira o consumo médio anual de iPhones desde 1900), será necessário fornecê-lo explicitamente à consulta.

    Observe que, ao calcular as médias anuais, talvez você queira omitir os registros do ano atual, pois ele ainda não terminou e provavelmente distorcerá seus dados.

    SELECT  i.Id, SUM(COALESCE(QuantityUsed, 0)) * 1. / (DATEDIFF(year, '2014-01-01', GETDATE()) + 1) -- start of the time span you're interested in.
    FROM    Items i -- list of all the items in the system
    LEFT JOIN
            ItemTransactions it
    ON      it.ItemNumber = i.Id
            AND it.DateUsed < DATETRUNC(year, GETDATE())
            AND it.DateUsed >= '2014-01-01'
    GROUP BY
            i.Id
    

    Isso também lhe dará a resposta correta de zero para os itens que nunca foram consumidos em uma transação, em vez de omiti-los do conjunto de resultados.

    Primeira transação como data de início

    Você pode querer tratar a primeira transação que aconteceu com o item como a data de sua introdução. Neste caso, use isto:

    SELECT  i.Id, COALESCE(SUM(QuantityUsed) * 1. / (DATEDIFF(year, MIN(DateUsed), GETDATE()), 0) + 1)
    FROM    Items i -- list of all the items in the system
    LEFT JOIN
            ItemTransactions it
    ON      it.ItemNumber = i.Id
            AND it.DateUsed < DATETRUNC(year, GETDATE())
    GROUP BY
            i.Id
    

    Datas reais

    Seu sistema também pode estar armazenando as datas reais de introdução e, possivelmente, de descontinuação de cada item. Neste caso, basta colocar essas datas na DATEDIFFfunção da SELECTcláusula.

    • 2

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve