Cập nhật các đơn đặt hàng mở từ bảng giá trong một phạm vi ngày


7

Thiết lập

Tôi đã thiết lập một ví dụ về rextesterdbfiddle .

Kịch bản

Bảng giá : Đó là bảng giá sản phẩm, một Sản phẩm có thể có nhiều hơn một mức giá hoạt động, thậm chí là một mức giá trong tương lai.

+---------+-------+------------+--------+--------+
| 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   |
+---------+-------+------------+--------+--------+

Đơn đặt hàng Các đơn đặt hàng đang chờ xử lý có giá và ngày đặt hàng

+---------+------------+-------+--------+
| 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  |
+---------+------------+-------+--------+

Mỗi khi chúng tôi thêm một mức giá mới trong danh sách, chúng tôi phải cập nhật các hàng bị chờ xử lý.

Ví dụ: nếu chúng ta thêm:

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

Bảng giá mới phải là:

+---------+------------+-------+--------+
| 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  |
+---------+------------+-------+--------+

Tôi muốn cập nhật các hồ sơ bị ảnh hưởng bằng một truy vấn duy nhất.

Do có một mức giá khác bắt đầu từ ngày 27.02.2017, các đơn đặt hàng ngày 28.02.2017 không bị ảnh hưởng bởi giá chèn.

Quá trình thực tế

Đến bây giờ, tôi sử dụng một truy vấn con tìm kiếm ngày đầu tiên khớp với bảng danh sách giá, nhưng bây giờ tôi cũng cần cập nhật basetrường. (Và hai hoặc ba trường nữa) và tôi muốn tránh sử dụng hai hoặc nhiều truy vấn con.

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

Xin vui lòng, để sửa văn bản của tôi, tôi biết ngữ pháp tiếng Anh của tôi không đủ tốt.


'Quy trình thực tế' của bạn có làm những gì bạn muốn không, nhưng bạn chỉ không muốn có nhiều truy vấn phụ? Đó là lý do tại sao tôi cung cấp CROSS ỨNG DỤNG (đã xóa câu trả lời ngay bây giờ) như một giải pháp khả thi. ỨNG DỤNG CROSS cho phép bạn 'tham gia' với phần truy vấn phụ dưới dạng bảng và kéo bất kỳ cột nào bạn cần.
Scott Hodgin

Đến bây giờ tôi chỉ cập nhật giá, nhưng có những yêu cầu mới và tôi không muốn sử dụng nhiều truy vấn con nếu có thể.,
McNets

vậy, tại sao bạn không thể sử dụng CROSS ỨNG DỤNG và SET o.price = ca.price, o.Base = ca.Base, o.AnyOtherColumn = ca.AnyOtherColumn?
Scott Hodgin

Vâng tôi cũng nghĩ thế.
McNets

Câu trả lời:


5

Tôi đã sử dụng mã dbfiddler của bạn trong giải pháp sau sử dụng CROSS ỨNG DỤNG

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;

Ok, hãy để tôi kiểm tra nó trong db của tôi, nhưng nó trông rất tốt. Cảm ơn.
McNets

Xin chào, tôi đang thử nghiệm trên máy chủ dàn của mình, nó hoạt động tốt, nhưng đến bây giờ tất cả các đơn đặt hàng đều được cập nhật. Bởi vì nó sẽ chạy trên một trình kích hoạt, bạn có nghĩ rằng chỉ có thể nâng cấp các đơn đặt hàng bị ảnh hưởng bởi bảng giá mới không?
McNets

Theo bảng giá mới, ý tôi là sử dụngselect price, base, date_price from inserted
McNets

Chà - điều đó 'nghe có vẻ hợp lý - tôi không thể nghĩ ngay đến bất kỳ lý do nào không hoạt động ... Tôi chắc chắn sẽ' kiểm tra 'điều đó trong một môi trường phi sản xuất.
Scott Hodgin

0

Trước hết tôi muốn cảm ơn @ScottHodgin vì đã làm việc để giải quyết câu hỏi của tôi.

Mặc dù câu trả lời của anh ấy đã giải quyết chính xác vấn đề, nhưng nó cập nhật tất cả các đơn đặt hàng đang hoạt động cho một sản phẩm cụ thể. Và tôi muốn tìm một giải pháp chỉ cập nhật các đơn đặt hàng bị ảnh hưởng bởi ngày niêm yết giá mới.

Vì quy trình này được thực thi trong một kích hoạt, tôi cần tạo một danh sách các khoảng thời gian để so sánh với ngày của các đơn đặt hàng.

Tôi đang thêm một ngày vào 'next_date' nếu không có bản ghi PriceList tiếp theo, chỉ để so sánh với <=.

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

Sau khi giải quyết vấn đề về phạm vi ngày, tôi chỉ cần cập nhật các đơn đặt hàng trong phạm vi này.

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);

Sau khi chèn hai bản ghi:

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);

Đây là kết quả cuối cùng:

|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|       |

Nếu ai đó quan tâm, tôi đã thiết lập một ví dụ dbfiddle .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.