Bring the first line based on an SQL date

Asked

Viewed 1,565 times

1

One more challenge stopped in my hands. I need help in my query.

What I need:

I want to know who are the people who have had account releases on a given day, where I need to show the value and situation of that day.

Being so, I have two tables, one that has the lasso of the person and the other that I have the values and the situation.

Table and data

This table is a history that stores information according to modifications, not necessarily occur every day.

Histpessoa Table

PessoaId | Situacao | DataInsert | Valor
  999    |   Ativo  | 2018-01-10 | 1111
  999    |   Ativo  | 2018-01-12 | 2222
  999    |   Ativo  | 2018-01-13 | 3333
  999    |   Inativo| 2018-01-18 | 4444
  999    |   Ativo  | 2018-01-20 | 5555
  999    |   Inativo| 2018-01-22 | 5555
  999    |   Ativo  | 2018-01-25 | 6666

Table Lancamento

PessoaId | LacamentoId | DataLancamento | Descrocao
   999   |    0001     |  2018-01-17    | Lacamento 1
   999   |    0002     |  2018-01-25    | Lacamento 2
   999   |    0003     |  2018-01-24    | Em divida com o sistema, liberação negada
   999   |    0002     |  2018-01-25    | Lacamento 2 estornado

General remarks: The Histpessoa table keeps a hostile all the time valor or situação is changed. Through the release date I need to inform the situation and the person’s value on the day of launch.

Example: On January 17, 2018 the person 999 was in situation Active with value of 3333. And on January 25, 2018 person 999 was in a situation Active with value of 6666

At launch 0001 a DataLancamento (2018-01-17) does not exist in the table HistPessoa, in that case I should take the DataInsert previous to DataLacamento closer than the date 2018-01-13

HistPessoa has stored long-standing history, it is a very large table. It would be interesting to have an optimization.

Expected result

PessoaId | LacamentoId | DataLacamento | Situacao | Valor
   999   |   0001      |  2018-01-17   |  Ativo   | 3333
   999   |   0002      |  2018-01-25   |  Ativo   | 6666

What I’ve done so far

SELECT TOP 100 PERCENT
         ROW_NUMBER() OVER (PARTITION BY PessoaId ORDER BY DataInsert DESC) AS NUM,
         PessoaId,
         valor,
         Situacao
         FROM HistPessoa
         ORDER BY DataInsert DESC

This query sorts in descending order, but does not filter by date so it picks the last date inserted in the table HistPessoa.

Extra I’ve assembled something more complete based on my real solution. Where I leave by Lancamento in search of the other data. Follow the link in the most complete SQL Fiddle. HERE

Any tips? Or possible solution?

Maybe with CTE or Gaps And Island?

  • Puts an example of the expected result

  • SELECT * FROM HistPessoa WHERE PessoaId = @Lancamento_PessoaId AND DataInsert <= @Lancamento_DataLancamento ORDER BY DataInsert DESC ? (you would enter the desired values where you are '@Lancamento_') or you want the result of the two tables together?

  • @Marlontiedt added. For both types of Releases

  • @Pedrogaspar-Lobofx I edited the question and put the expected results. I need to make a Join between the tables

  • I understood very well your doubt no, but if you reformulate I can help you. I think remarks is a little confused to understand.

  • @Marconi was really bad. You can understand now?

  • @Emanuelf looks at my answer!

  • @Marconi I edited again, added the link to a new SQL Fiddle based on what you’ve assembled.

  • @Emanuelf already researched on and CTE will have the same processing of a sub-colony.

Show 5 more comments

1 answer

3


CREATE TABLE HISTPESSOA(
 PessoaId int,
 Situacao varchar(10),
 DataInsert date,
 Valor int
);

INSERT INTO HISTPESSOA(PessoaId,Situacao,DataInsert,Valor) values
(999,'Ativo','2018-01-10',1111),
(999,'Ativo','2018-01-12',2222),
(999,'Ativo','2018-01-13',3333),
(999,'Inativo','2018-01-18',4444),
(999,'Ativo','2018-01-20',5555),
(999,'Inativo','2018-01-22',5555),
(999,'Ativo','2018-01-25',6666);


CREATE TABLE LANCAMENTO(
 PessoaId int,
 LacamentoId int,
 DataLancamento date
);
INSERT INTO LANCAMENTO(PessoaId,LacamentoId,DataLancamento) values
(999,0001,'2018-01-17'),
(999,0002,'2018-01-25');

Query:

SELECT l.*
    FROM
      (SELECT HP.PessoaId,
              L.LacamentoId,
              L.DataLancamento,
              HP.Valor,
              ROW_NUMBER() OVER (PARTITION BY L.LacamentoId
                                 ORDER BY DataInsert DESC) AS linha
       FROM HISTPESSOA HP
       INNER JOIN LANCAMENTO L ON HP.PessoaId = L.PessoaId
       WHERE HP.DataInsert <= L.DataLancamento) l
    WHERE l.linha = 1;

Upshot:

inserir a descrição da imagem aqui

Explanation:

  • Use ROW_NUMBER to list your lines
  • Segment through the column LacamentoId.
  • Order downward the column DataInsert.
  • Take the first line as it will be the previous line you want!

I arrived there this result using as a basis this other answer my: Select first record within a segmentation in SQL Server

  • top 1 with ordination would not solve also?

  • @Jeffersonquesado think it would have to be so msm, so I understood yes. Any suggestions for improvement?

  • I’m not sure. I would test like I did, with top, but I’m not sure it would work

  • 1

    @Jeffersonquesado actually that’s kind of a Group by with top 1. He wants to catch the smallest record before the last Date release through an Idlancamento.

  • I think the ROW_NUMBER very long, not to mention that I have trouble understanding it, so I run away from it

  • 1

    @Jeffersonquesado in the answer I put a link to another answer, there is easier to understand, but he has to make a stop msm to understand how it works right.

  • Wouldn’t it be easier to use limit 1 in the end?

  • 1

    @Guillhermecostamilam limit 1 is from Mysql, in Mssql is top 1, but this will bring only 1 record, will not work!

  • @Marconi the result is as expected. The problem I noticed, is that the Lancamento table has more records for the same release with the same date. Using your solution. I haven’t been able to put this solution in my real context yet. I haven’t found a way to explain it, let me analyze it further. So far, it’s helped me think of a different way.

  • @Emanuelf if you edit your question with possible problems, change the query to help you.

  • @Marconi Yes, I intend to do this. (Help you to help me). The problem is also in the optimization, because the HistPessoa has several records and the query as shown by you, will enumerate all records from the DataLancamento.

  • @Emanuelf got it, edit it, man, let’s see what can help you :)

Show 7 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.