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 / 165102
Accepted
McNets
McNets
Asked: 2017-02-22 16:00:22 +0800 CST2017-02-22 16:00:22 +0800 CST 2017-02-22 16:00:22 +0800 CST

Atualizando pedidos em aberto de uma lista de preços dentro de um intervalo de datas

  • 772

Configurar

Eu configurei um exemplo em rextester e dbfiddle .

Cenário

Lista de preços : É a lista de preços dos produtos, um produto pode ter mais de um preço ativo, mesmo um preço futuro.

+---------+-------+------------+--------+--------+
| product | price | date_price |  base  | active |
+---------+-------+------------+--------+--------+
|   0125  |    90 | 01.01.2017 |  1200  |    0   |
|   0125  |   100 | 25.01.2017 |  1000  |    1   |
|   0125  |   110 | 27.02.2017 |   500  |    1   |
+---------+-------+------------+--------+--------+
|   1200  |   140 | 01.01.2017 |  2000  |    0   |
|   1200  |   150 | 01.02.2017 |  1500  |    1   |
|   1200  |   160 | 27.02.2017 |  1000  |    1   |
+---------+-------+------------+--------+--------+

Encomendas As encomendas pendentes têm um preço e uma data de encomenda

+---------+------------+-------+--------+
| product | order_date | price |  base  |
+---------+------------+-------+--------+
|   0125  | 19.02.2017 |  100  |  1000  |
|   0125  | 20.02.2017 |  100  |  1000  |
|   0125  | 21.02.2017 |  100  |  1000  |
|   0125  | 22.02.2017 |  100  |  1000  |
|   0125  | 23.02.2017 |  100  |  1000  |
|   0125  | 28.02.2017 |  110  |   500  |
+---------+------------+-------+--------+
|   1200  | 19.02.2017 |  150  |  1500  |
|   1200  | 20.02.2017 |  150  |  1500  |
|   1200  | 21.02.2017 |  150  |  1500  |
|   1200  | 22.02.2017 |  150  |  1500  |
|   1200  | 23.02.2017 |  150  |  1500  |
|   1200  | 28.02.2017 |  160  |  1000  |
+---------+------------+-------+--------+

Sempre que adicionamos um novo preço na lista, devemos atualizar as linhas afetadas de pedidos pendentes.

Por exemplo, se adicionarmos:

+---------+-------+------------+--------+--------+
| product | price | date_price |  base  | active |
+---------+-------+------------+--------+--------+
|   0125  |   105 | 21.02.2017 |  1300  |    1   |
|   1200  |   155 | 21.02.2017 |  1400  |    1   |
+---------+-------+------------+--------+--------+

A nova lista de preços deve ser:

+---------+------------+-------+--------+
| product | order_date | price |  base  |
+---------+------------+-------+--------+
|   0125  | 19.02.2017 |  100  |  1000  |
|   0125  | 20.02.2017 |  100  |  1000  |
|   0125  | 21.02.2017 |  105  |  1300  | *
|   0125  | 22.02.2017 |  105  |  1300  | * Affected rows
|   0125  | 23.02.2017 |  105  |  1300  | *
|   0125  | 28.02.2017 |  110  |   500  | 
+---------+------------+-------+--------+
|   1200  | 19.02.2017 |  150  |  1500  |
|   1200  | 20.02.2017 |  150  |  1500  |
|   1200  | 21.02.2017 |  150  |  1500  | *
|   1200  | 22.02.2017 |  150  |  1500  | * Affectd rows between 21.02.2017 and 27.02.2017
|   1200  | 23.02.2017 |  150  |  1500  | *
|   1200  | 28.02.2017 |  160  |  1000  |
+---------+------------+-------+--------+

Gostaria de atualizar os registros afetados usando uma única consulta.

Por existir outro preço a partir de 27.02.2017, os pedidos de 28.02.2017 não são afetados pelo preço inserido.

Processo real

Até agora, uso uma subconsulta que busca a primeira data que corresponde na tabela da lista de preços, mas agora preciso atualizar o basecampo também. (E mais dois ou três campos) e gostaria de evitar usar duas ou mais subconsultas.

update @orders
set    price = (select   top 1 pl.price
                from     @price_list pl
                where    pl.product = o.product
                and      pl.date_price <= o.order_date
                and      active = 1
                order by pl.date_price desc),
       base  = (select   top 1 pl.base
                from     @price_list pl
                where    pl.product = o.product
                and      pl.date_price <= o.order_date
                and      active = 1
                order by pl.date_price desc)
from   @orders o
where  o.product in ('0125', '1200');  --<<< select distinct product from inserted

Por favor, sinta-se à vontade para corrigir meu texto, eu sei que minha gramática inglesa não é boa o suficiente.

sql-server sql-server-2005
  • 2 2 respostas
  • 169 Views

2 respostas

  • Voted
  1. Best Answer
    Scott Hodgin - Retired
    2017-02-23T06:15:16+08:002017-02-23T06:15:16+08:00

    Eu usei seu código dbfiddler na seguinte solução que usa CROSS APPLY

    declare @price_list table(product varchar(20), price int, date_price datetime, base int, active tinyint);
    insert into @price_list values
    ('0125',  90, '2017-01-01', 1200, 0), 
    ('0125', 100, '2017-01-25', 1000, 1), 
    ('0125', 110, '2017-02-27', 500,  1),
    ('1200', 140, '2017-01-01', 2000, 0), 
    ('1200', 150, '2017-02-01', 1500, 1), 
    ('1200', 160, '2017-02-27', 1000, 1);
    
    declare @orders table(product varchar(20), order_date datetime, price int, base int);
    insert into @orders values
    ('0125', '2017-02-19', 100, 1000), 
    ('0125', '2017-02-20', 100, 1000),
    ('0125', '2017-02-21', 100, 1000), 
    ('0125', '2017-02-22', 100, 1000),
    ('0125', '2017-02-23', 100, 1000), 
    ('0125', '2017-02-28', 110,  500),
    ('1200', '2017-02-19', 150, 1500), 
    ('1200', '2017-02-20', 150, 1500),
    ('1200', '2017-02-21', 150, 1500), 
    ('1200', '2017-02-22', 150, 1500),
    ('1200', '2017-02-23', 150, 1500), 
    ('1200', '2017-02-28', 160, 1000);
    
    
    
    declare @new_date_price datetime = '2017-02-21';
    
    
    -- add a new price to the list
    --
    insert into @price_list values ('0125', 105, @new_date_price - 1, 1300, 1);
    insert into @price_list values ('1200', 155, @new_date_price - 1, 1400, 1);
    
    
    -- update orders price and base, according products price list date price
    --
    -- I'd like to avoid use 2 (or more) subqueries
    --
    UPDATE o
    SET o.Price = ca.price
        ,o.base = ca.base
    FROM @Orders o
    CROSS APPLY (
        SELECT TOP 1 pl.price AS price
            ,pl.base AS base
        FROM @Price_List pl
        WHERE pl.product = o.product
            AND pl.date_price <= o.order_date
            AND active = 1
        ORDER BY pl.date_price DESC
        ) ca
    WHERE o.product IN (
            '0125'
            ,'1200'
            );--<<< select distinct product from inserted
    -- final result
    --
    select * from @price_list order by product, date_price;
    select * from @orders order by product, order_date;
    
    • 5
  2. McNets
    2017-02-24T02:36:35+08:002017-02-24T02:36:35+08:00

    Em primeiro lugar, quero agradecer a @ScottHodgin por seu trabalho para resolver minha pergunta.

    Embora sua resposta tenha resolvido corretamente o problema, ela atualiza todos os pedidos ativos de um determinado produto. E eu queria encontrar uma solução que atualizasse apenas os pedidos afetados pela nova data da lista de preços.

    Como esse procedimento é executado dentro de uma trigger, preciso gerar uma lista de intervalos de datas para comparar com a data dos pedidos.

    Estou adicionando um dia a 'next_date' se não houver próximo registro PriceList, apenas para comparar com <=.

    SELECT product, price, date_price, base, active,
           (SELECT TOP 1     pl.date_price
                   FROM      PriceList pl
                   WHERE     pl.product = i.product
                   AND       pl.date_price > i.date_price
                   AND       pl.active > 0
                   ORDER BY  pl.date_price ASC) next_date
    FROM inserted i
    

    Uma vez resolvido o problema do intervalo de datas, só preciso atualizar os pedidos dentro desse intervalo.

    WITH PList AS
    (
    SELECT product, price, date_price, base, active,
           (SELECT TOP 1     pl.date_price
                   FROM      PriceList pl
                   WHERE     pl.product = i.product
                   AND       pl.date_price > i.date_price
                   AND       pl.active > 0
                   ORDER BY  pl.date_price ASC) next_date
    FROM inserted i
    )
    UPDATE     Orders
    SET        price = PList.price,
               base  = PList.base,
               [status] = 'Updated'
    FROM       Orders o
    INNER JOIN Plist
    ON         Plist.product = o.product 
    AND        o.order_date >= Plist.date_price
    AND        o.order_date < COALESCE(Plist.next_date, DATEADD(DAY, 1, Plist.next_date);
    

    Após inserir dois registros:

    DECLARE @new_date_price datetime = '2017-02-21';
    
    INSERT INTO PriceList VALUES 
    ('0125', 105, @new_date_price, 1300, 2),
    ('1200', 155, @new_date_price, 1400, 2);
    

    Esse é o resultado final:

    |product|order_date  |price|base|status |
    |:------|:-----------|----:|---:|:------|
    |0125   |Feb 19 2017 |  100|1000|       |
    |0125   |Feb 20 2017 |  100|1000|       |
    |0125   |Feb 21 2017 |  105|1300|Updated|
    |0125   |Feb 22 2017 |  105|1300|Updated|
    |0125   |Feb 23 2017 |  105|1300|Updated|
    |0125   |Feb 28 2017 |  110| 500|       |
    |1200   |Feb 19 2017 |  150|1500|       |
    |1200   |Feb 20 2017 |  150|1500|       |
    |1200   |Feb 21 2017 |  155|1400|Updated|
    |1200   |Feb 22 2017 |  155|1400|Updated|
    |1200   |Feb 23 2017 |  155|1400|Updated|
    |1200   |Feb 28 2017 |  160|1000|       |
    

    Se alguém estiver interessado, eu configurei um exemplo dbfiddle .

    • 0

relate perguntas

  • 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

  • Downgrade do SQL Server 2008 para 2005

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