Selezionare i record che hanno cambiato i suoi valori precedenti

voti
0

Ho una tabella in cui mi registro la storia del prezzo dei prodotti in un catalogo (un'altra tabella).

Il prezzo di qualsiasi prodotto può cambiare in qualsiasi momento, quindi ho bisogno di identificare solo ciò che i prodotti hanno cambiato i loro prezzi. Per esempio io ho questa tabella:

+----+--------------+-------+---------------------+
| id | product_code | price | price_date          |
+----+--------------+-------+---------------------+
|  1 | P01          | 10.00 | 2019-01-01 00:00:00 |
|  2 | P01          | 15.00 | 2019-01-03 00:00:00 |
|  3 | P01          | 20.00 | 2019-01-05 00:00:00 |
|  4 | P01          | 15.00 | 2019-01-09 00:00:00 |
|  5 | P02          | 10.00 | 2019-01-04 00:00:00 |
|  6 | P02          | 15.00 | 2019-01-06 00:00:00 |
|  7 | P02          | 15.00 | 2019-01-07 00:00:00 |
|  8 | P03          | 15.00 | 2019-01-09 00:00:00 |
|  9 | P04          | 15.00 | 2019-01-01 00:00:00 |
| 10 | P04          | 15.00 | 2019-01-02 00:00:00 |
| 11 | P04          | 25.00 | 2019-01-05 00:00:00 |
| 12 | P05          | 15.00 | 2019-01-01 00:00:00 |
| 13 | P05          | 15.00 | 2019-01-02 00:00:00 |
+----+--------------+-------+---------------------+

e ho bisogno di questo risultato:

+--------------+-------+---------------------+
| product_code | price | price_date          |
+--------------+-------+---------------------+
|          P01 | 20.00 | 2019-01-05 00:00:00 |
|          P01 | 15.00 | 2019-01-09 00:00:00 |
|          P04 | 15.00 | 2019-01-02 00:00:00 |
|          P04 | 25.00 | 2019-01-05 00:00:00 |
+--------------+-------+---------------------+

e questo sono le eccezioni:

P02 non ha cambiato il suo prezzo così lo ignoro (più volte sì, lo stesso prezzo può essere registrato consecutivamente)

P03 hanno solo 1 registro, quindi tecnicamente non ha modificato il suo prezzo, in modo da ignorare (questo sono molto rari, ma alcuni prodotti non cambiano mai i loro prezzi)

P05 non ha cambiato il suo prezzo così lo ignoro

Ho messo questo dati al fine di leggere facilmente, ma tecnicamente i dati possono essere in qualsiasi ordine.

Vi mando la query in modo da non sprecare troppo tempo:

CREATE TABLE PriceHistory(
id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL,
product_code CHAR(3) NOT NULL,
price DECIMAL(5,2) NOT NULL,
price_date DATETIME NOT NULL,
PRIMARY KEY (id));

INSERT INTO PriceHistory(product_code, price, price_date) VALUES
('P01', 10, '2019-01-01'),
('P01', 15, '2019-01-03'),
('P01', 20, '2019-01-05'),
('P01', 15, '2019-01-09'),
('P02', 10, '2019-01-04'),
('P02', 15, '2019-01-06'),
('P02', 15, '2019-01-07'),
('P03', 15, '2019-01-09'),
('P04', 15, '2019-01-01'),
('P04', 15, '2019-01-02'),
('P04', 25, '2019-01-05'),
('P05', 15, '2019-01-01'),
('P05', 15, '2019-01-02');

Grazie in anticipo.

È pubblicato 10/10/2019 alle 00:50
fonte dall'utente
In altre lingue...                            


2 risposte

voti
0

La sua risposta non precisa l'esatto perché mi aspetto di avere i risultati su ciascuna riga, ma questa risposta è abbastanza buono e di ottenere il lavoro fatto:

SELECT info1.*, info2.* FROM
(SELECT lasts.product_code, lasts.id AS last_id, penultimate.id AS penultimate_id FROM
    (SELECT product_code, MAX(id) AS id FROM PriceHistory GROUP BY product_code HAVING COUNT(product_code) > 1) lasts
INNER JOIN
    (SELECT product_code, MAX(id) AS id FROM PriceHistory WHERE id NOT IN (SELECT MAX(id) FROM PriceHistory GROUP BY product_code) GROUP BY product_code) penultimate
ON lasts.product_code = penultimate.product_code) relations
INNER JOIN PriceHistory info1 ON relations.last_id = info1.id
INNER JOIN PriceHistory info2 ON relations.penultimate_id = info2.id
WHERE info1.price != info2.price

E dà questo risultato:

+----+--------------+-------+---------------------+----+--------------+-------+---------------------+
| id | product_code | price | price_date          | id | product_code | price | price_date          |
+----+--------------+-------+---------------------+----+--------------+-------+---------------------+
|  4 | P01          | 15.00 | 2019-01-09 00:00:00 |  3 | P01          | 20.00 | 2019-01-05 00:00:00 |
| 11 | P04          | 25.00 | 2019-01-05 00:00:00 | 10 | P04          | 15.00 | 2019-01-02 00:00:00 |
+----+--------------+-------+---------------------+----+--------------+-------+---------------------+
Risposto il 10/10/2019 a 22:00
fonte dall'utente

voti
0

Questo appare come un caso d'uso naturale per la funzione finestra LAG(), disponibile in MySQL 8.0:

SELECT product_code, price, price_date 
FROM (
    SELECT
        t.*,
        LAG(price) OVER(PARTITION BY product_code ORDER BY price_date) lag_price
    FROM PriceHistory t
) x WHERE price != lag_price

Demo su DB Fiddle - sembra che non ci sono discrepanze nei risultati attesi che ha mostrato, ma questo mi sembra l'uscita corretta in base alla mia comprensione della vostra domanda:

| product_code | price | price_date          |
| ------------ | ----- | ------------------- |
| P01          | 15    | 2019-01-03 00:00:00 |
| P01          | 20    | 2019-01-05 00:00:00 |
| P01          | 15    | 2019-01-09 00:00:00 |
| P02          | 15    | 2019-01-06 00:00:00 |
| P04          | 25    | 2019-01-05 00:00:00 |
Risposto il 10/10/2019 a 00:57
fonte dall'utente

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more