none
Selecionar maior data RRS feed

  • Pergunta

  •  

    Oi Galera,

    Tenho uma tabela de de compras onde tenho a data da compra e o Id do cliente.

    Como faço para selecionar somente a data mais recente de cada cliente, mesmo se um cliente tiver 100 registros, quero trazer só a ultima data ( que será a maior) e o id do cliente?

     

    Valeu.

    segunda-feira, 29 de setembro de 2008 15:08

Respostas

  • Boa Tarde,

     

    De fato fiquei devendo o GROUP BY. Tente o seguinte:

     

    Code Snippet

    -- Se todos os veículos tiverem posições

    SELECT VEC.IDVEICULO, VEC.PLACA, VEC.ANO, VEC.COR,

    MAX(DATAEVENTO) AS UltimaPosicao

    FROM Veiculos AS VEC

    INNER JOIN Posicoes AS POS ON VEC.IDVeiculo = POS.IDVeiculo

    WHERE VEC.IDCliente = 27

    GROUP BY VEC.IDVEICULO, VEC.PLACA, VEC.ANO, VEC.COR

     

    -- Se houver veículos que não necessariamente tem posições

    SELECT VEC.IDVEICULO, VEC.PLACA, VEC.ANO, VEC.COR,

    MAX(DATAEVENTO) AS UltimaPosicao

    FROM Veiculos AS VEC

    LEFT JOIN Posicoes AS POS ON VEC.IDVeiculo = POS.IDVeiculo

    WHERE VEC.IDCliente = 27

    GROUP BY VEC.IDVEICULO, VEC.PLACA, VEC.ANO, VEC.COR

     

     

    [ ]s,

     

    Gustavo

    terça-feira, 30 de setembro de 2008 20:01

Todas as Respostas

  • Fernando,

     

    Segue SQL abaixo:

     

    Code Snippet

    SELECT CodigoCliente, MAX(DataCompra) AS DataRecenteCompra

    FROM Compras

    GROUP BY CodigoCliente

     

     

     

    Att.


    Ari C. Raimundo

     

    segunda-feira, 29 de setembro de 2008 15:15
  • Oi Ari, tá retornando muita linha, mais do que deveria.

    Tenho 15 clientes na tabela e cada um tem um monte de compras, mas quero só á última compra de cada, tá retornando mais de 600 linhas, tem que retornar só 15.

     

    Abç.

    segunda-feira, 29 de setembro de 2008 15:36
  • Boa Tarde,

     

    Acho difícil do código do Ari estar errado a menos que haja códigos de clientes parecidos (ex: 'CLI1', 'CLI1 '). Em todo caso, tente o seguinte código:

     

    Code Snippet

    SELECT Cli.IDCliente,

    (SELECT MAX(DataCompra) FROM tblCompras AS Comp

    WHERE Cli.IDCliente = Comp.IDCliente) AS MaiorCompra

    FROM

    (SELECT DISTINCT IDCliente FROM tblCompras) AS Cli

     

     

    [ ]s,

     

    Gustavo

    segunda-feira, 29 de setembro de 2008 16:49
  • Maia,

     

    Também acho estranho, a não ser que ele tenha algumas linhas redundantes!!!

    segunda-feira, 29 de setembro de 2008 17:06
  • Fernando,

     

    Pode mostrar a estrutura da tabela aqui no fórum ?

     

    Att.

     

    Ari C. Raimundo

    segunda-feira, 29 de setembro de 2008 17:15
  •  

    Insira também na sua clausula FROM, após o IDCliente - , DataCompra

    Ela também precisa entrar na especificação de DISTINCT

     

    Você deve verificar também o seguinte: Um cliente pode ter duas compras na mesma data!!! O que poderia apresentar duplicação de dados caso você não especifique algum campo diferente, como por exemplo, HoraCompra.

    Insira então também o DISTINCT se necessário, na segunda linha: SELECY DISTINCT MAX(.................

     

    Caso contrário, segue exemplo

     

    SELECT Cli.IDCliente,

    (SELECT MAX(DataCompra) FROM tblCompras AS Comp

    WHERE Cli.IDCliente = Comp.IDCliente) AS MaiorCompra

    FROM

    (SELECT DISTINCT IDCliente, DataCompra FROM tblCompras) AS Cli

     

    Abraço!

    terça-feira, 30 de setembro de 2008 12:54
  • Bom Dia,

     

    A coluna DataCompra é dispensável no DISTINCT uma vez que você está recuperando a data da compra na subquery com o MAX(Compra). Colocá-la na consulta irá trazer um resultado indesejável e dispendioso.

     

    Como o DISTINCT será com o IDCliente e o DataCompra, o IDCliente irá se repetir, pois, existirão várias compras para um mesmo cliente. Se ele se repetir na tabela derivada, quando consultarmos no SELECT mais externo, teremos repetições para o IDCliente e o MAX(Compra) para cada uma dessas repetições. Se o DISTINCT trouxer por exemplos três vezes o cliente 1 (uma para cada data), o SELECT mais externo retornará o cliente 1 três vezes e fará o MAX(Compra) três vezes.

     

    Fiz essa consulta mais por desencargo, mas acho que a consulta do ARI já está correta, uma vez que GROUP BY já é um DISTINCT nato e elimina repetições.

     

    [ ]s,

     

    Gustavo

     

    terça-feira, 30 de setembro de 2008 13:28
  • Fala galera,

    Vamos fazer assim, vou colocar um exemplo pratico de onde preciso usar essa select e vou colocar a estrutura das tabelas.

     

    Meu sistema tem 3 tabelas VEICULOS, CLIENTES e POSICOES abaixo segue a estrutura das tabelas.

     

    CREATE TABLE [dbo].[VEICULOS](

    [IDVEICULO] [int] NOT NULL,

    [PLACA] [nvarchar](8) NULL,

    [ANO] [nvarchar](4) NULL,

    [COR] [nvarchar](30) NULL,

    [IDCLIENTE] [int] NULL,

    CONSTRAINT [PK_VEICULOS] PRIMARY KEY CLUSTERED

    (

     

    CREATE TABLE [dbo].[CLIENTES](

    [IDCLIENTE] [int] NOT NULL,

    [NOME] [nvarchar](50) NULL,

    [ENDERECO] [nvarchar](50) NULL,

    [CIDADE] [nvarchar](25) NULL,

    [CEP] [nvarchar](11) NULL,

    [ESTADO] [nvarchar](2) NULL,

    [EMAIL] [nvarchar](100) NULL,

    CONSTRAINT [PK_CLIENTE] PRIMARY KEY CLUSTERED

    (

     

    CREATE TABLE [dbo].[GSTB_HISTORICO](

    [IDPOSICAO] [int] IDENTITY(1,1) NOT FOR REPLICATION NOT NULL,

    [IDVEICULO] [int] NULL,

    [LOCAL] [nvarchar](10) NULL,

    [DATAATUAL] [datetime] NULL,

    [DATAEVENTO] [datetime] NULL,

    ) ON [PRIMARY]

     

    Cada cliente pode ter vários veículos, e cada veículos pode ter várias posições.

     

    Preciso selecionar a última posição de todos os veículos de um cliente por exemplo ID=27.

    A última posição é a que tiver o campo DATAEVENTO maior.

    Como faço isso?

     

    Valeu.

    terça-feira, 30 de setembro de 2008 18:49
  •  

    No meu último post no código de criar a tabela, o nome da tabela está GSTB_HISTORICO e o correto é POSICOES.
    terça-feira, 30 de setembro de 2008 18:52
  • Boa Tarde,

     

    Verifique se o SELECT abaixo o atende:

     

    Code Snippet

    -- Se todos os veículos tiverem posições

    SELECT VEC.*, MAX(DATAEVENTO) AS UltimaPosicao

    FROM Veiculos AS VEC

    INNER JOIN Posicoes AS POS ON VEC.IDVeiculo = POS.IDVeiculo

    WHERE VEC.IDCliente = 27

     

    -- Se houver veículos que não necessariamente tem posições

    SELECT VEC.*, MAX(DATAEVENTO) AS UltimaPosicao

    FROM Veiculos AS VEC

    LEFT JOIN Posicoes AS POS ON VEC.IDVeiculo = POS.IDVeiculo

    WHERE VEC.IDCliente = 27

     

     

    [ ]s,

     

    Gustavo

    terça-feira, 30 de setembro de 2008 19:25
  • Oi Gustavo, da esse erro:

     

    Msg 8118, Level 16, State 1, Line 3

    Column 'VEC.IDVEICULO' is invalid in the select list because it is not contained in an aggregate function and there is no GROUP BY clause.

    Msg 8118, Level 16, State 1, Line 3

    Column 'VEC.IDENTIFICACAO' is invalid in the select list because it is not contained in an aggregate function and there is no GROUP BY clause.

    Msg 8118, Level 16, State 1, Line 3

    Column 'VEC.PLACA' is invalid in the select list because it is not contained in an aggregate function and there is no GROUP BY clause.

    Msg 8118, Level 16, State 1, Line 3

    terça-feira, 30 de setembro de 2008 19:48
  • O código está OK, falto apenas a clausula GROUP BY.
    coloque após o seu WHERE
    GROUP BY as colunas. separadas por virgulas. Para organizar o código, coloque-as na ordem do erro
    Veja se isso ajuda

    Vinicius

    terça-feira, 30 de setembro de 2008 19:52
  • Boa Tarde,

     

    De fato fiquei devendo o GROUP BY. Tente o seguinte:

     

    Code Snippet

    -- Se todos os veículos tiverem posições

    SELECT VEC.IDVEICULO, VEC.PLACA, VEC.ANO, VEC.COR,

    MAX(DATAEVENTO) AS UltimaPosicao

    FROM Veiculos AS VEC

    INNER JOIN Posicoes AS POS ON VEC.IDVeiculo = POS.IDVeiculo

    WHERE VEC.IDCliente = 27

    GROUP BY VEC.IDVEICULO, VEC.PLACA, VEC.ANO, VEC.COR

     

    -- Se houver veículos que não necessariamente tem posições

    SELECT VEC.IDVEICULO, VEC.PLACA, VEC.ANO, VEC.COR,

    MAX(DATAEVENTO) AS UltimaPosicao

    FROM Veiculos AS VEC

    LEFT JOIN Posicoes AS POS ON VEC.IDVeiculo = POS.IDVeiculo

    WHERE VEC.IDCliente = 27

    GROUP BY VEC.IDVEICULO, VEC.PLACA, VEC.ANO, VEC.COR

     

     

    [ ]s,

     

    Gustavo

    terça-feira, 30 de setembro de 2008 20:01
  • Oi Gustavo, estamos quase lá .

     

    Agora voltou o número de linha que tinha que ter voltado mesmo, só que na sua query vc retorna os campos da tabela VEICULOS e o que me interessa são os campos da tabela POSICOES.

     

     

    Valeu.

     

     

     

    terça-feira, 30 de setembro de 2008 20:15
  • O SELECT está sendo feito em veículos. Veja o seu FROM
    Você deve alterar para a tabela de onde quer pegar as informações.
    Isso vai fazer com que você altere todos os campos e apelidos no SELECT e no GROUP BY

     

    abraços

     

    terça-feira, 30 de setembro de 2008 20:24
  • Oi Fernando,

     

    Acho que agora eu entendi sua dúvida e por que você fala das supostas repetições.

     

    Vamos ver se eu entendi mesmo. Tente o código abaixo:

     

    Code Snippet

    SELECT Q.*, POS.* FROM

    (SELECT VEC.IDVEICULO, VEC.PLACA, VEC.ANO, VEC.COR,

    MAX(DATAEVENTO) AS UltimaData

    FROM Veiculos AS VEC

    INNER JOIN Posicoes AS POS ON VEC.IDVeiculo = POS.IDVeiculo

    WHERE VEC.IDCliente = ?

    GROUP BY VEC.IDVEICULO, VEC.PLACA, VEC.ANO, VEC.COR) AS Q

    INNER JOIN POSICOES AS POS

    ON Q.IDVeiculo = POS.IDVeiculo AND Q.UltimaData = POS.DataAtual

     

     

    [ ]s,

     

    Gustavo

    terça-feira, 30 de setembro de 2008 20:29
  • Oi Gustavo,

    Estamos quase lá.

     

    Usei essa query

     

    SELECT Q.*, POS.* FROM

    (SELECT VEC.IDVEICULO,

    MAX(DATAEVENTO) AS UltimaData

    FROM VEICULOS AS VEC

    INNER JOIN POSICOES AS POS ON VEC.IDVeiculo = POS.IDVeiculo

    WHERE VEC.IDCliente = 28

    GROUP BY VEC.IDVEICULO) AS Q

    INNER JOIN POSICOES AS POS

    ON Q.IDVeiculo = POS.IDVeiculo AND Q.UltimaData = POS.DATAEVENTO

     

    Da tabela veículos eu preciso só a placa o resto não me interessa, e com essa sua select tá retornando as placas erradas, o IDVEICULO retornado não bate com a PLACA.

     

    E tem mais um lance acontecendo, percebi que a tabela POSICOES tem registros duplicados, tem como filtrar para não trazer os duplicados?

     

    Valeu.

     

    quarta-feira, 1 de outubro de 2008 14:47