2013-01-22 38 views
7

Tôi có một bảng như thế này:Làm thế nào để cập nhật X% hàng để A, Y% hàng đến B, Z% hàng để C

Products 
(
    ID int not null primary key, 
    Type int not null, 
    Route varchar(20) null 
) 

tôi có một danh sách trên máy khách ở định dạng này :

Type=1, Percent=0.4, Route=A 
Type=1, Percent=0.4, Route=B 
Type=1, Percent=0.2, Route=C 
Type=2, Percent=0.5, Route=A 
Type=2, Percent=0.5, Route=B 
Type=3, Percent=1.0, Route=C 
...etc 

Khi hoàn tất, tôi muốn chỉ định 40% của các loại sản phẩm từ 1 tới Route A, 40% đến Route B và 20% đến Route C. Sau đó 50% các sản phẩm loại 2 đến Route A và 50% sản phẩm loại 2 đến Tuyến đường B, v.v.

Có cách nào để thực hiện việc này trong một lần cập nhật đơn lẻ không tatement?

Nếu không có trong một tuyên bố khổng lồ, nó có thể được thực hiện trong một tuyên bố cho mỗi loại hoặc một tuyên bố trên mỗi tuyến đường không? Hiện tại, chúng tôi đang thực hiện một loại cho mỗi loại + tuyến đường bất kỳ ở trên sẽ là một cải tiến.

+0

"Phần trăm" trong danh sách của bạn là khá gây hiểu nhầm nếu con số tiếp theo không thực sự là tỷ lệ phần trăm . –

+0

Bạn đang sử dụng DBMS nào? Ngoài ra, bạn có thể đăng mã hoặc mã giả của giải pháp hiện tại của mình không? –

+0

SQL Server 2008. Và 0,4 không phải là một phần trăm? 40.0 có tốt hơn không? Tôi giả sử 0,4 là tốt hơn bởi vì 0,4 * đếm (*) là số hàng cần cập nhật. – powlette

Trả lời

1

Đây là một câu lệnh Oracle mà tôi đã chuẩn bị trước khi bạn đăng tải rằng bạn đang sử dụng SQL Server, nhưng nó có thể cung cấp cho bạn một số ý tưởng, mặc dù bạn sẽ phải cuộn chức năng phân tích tỷ lệ của riêng bạn bằng CTE và tự tham gia. Chúng tôi tính toán tỷ lệ tích lũy của từng loại trong bảng định tuyến sản phẩm và khách hàng và thực hiện không tham gia vào các dải tỷ lệ phù hợp. Dữ liệu mẫu mà tôi đã sử dụng có một số lần bù trừ nhưng chúng sẽ giảm cho các tập dữ liệu lớn hơn.

Dưới đây là các thiết lập:

create table products (id int not null primary key, "type" int not null, route varchar (20) null); 
create table clienttable ("type" int not null, percent number (10, 2) not null, route varchar (20) not null); 
insert into clienttable ("type", percent, route) values (1, 0.4, 'A'); 
insert into clienttable ("type", percent, route) values (1, 0.4, 'B'); 
insert into clienttable ("type", percent, route) values (1, 0.2, 'C'); 
insert into clienttable ("type", percent, route) values (2, 0.5, 'A'); 
insert into clienttable ("type", percent, route) values (2, 0.5, 'B'); 
insert into clienttable ("type", percent, route) values (3, 1.0, 'C'); 

insert into products (id, "type", route) values (1, 1, null); 
insert into products (id, "type", route) values (2, 1, null); 
insert into products (id, "type", route) values (3, 1, null); 
insert into products (id, "type", route) values (4, 1, null); 
insert into products (id, "type", route) values (5, 1, null); 
insert into products (id, "type", route) values (6, 1, null); 
insert into products (id, "type", route) values (7, 1, null); 
-- 7 rows for product type 1 so we will expect 3 of route A, 3 of route B, 1 of route C (rounded) 

insert into products (id, "type", route) values (8, 2, null); 
insert into products (id, "type", route) values (9, 2, null); 
insert into products (id, "type", route) values (10, 2, null); 
insert into products (id, "type", route) values (11, 2, null); 
insert into products (id, "type", route) values (12, 2, null); 
-- 5 rows for product type 2 so we will expect 3 of route A and 2 of route B (rounded) 

insert into products (id, "type", route) values (13, 3, null); 
insert into products (id, "type", route) values (14, 3, null); 
-- 2 rows for product type 3 so we will expect 2 of route C 

và đây là báo cáo kết quả

select prods.id, prods."type", client.route cr from 
(
select 
p.id, 
p."type", 
row_number() over (partition by p."type" order by p.id)/count (*) over (partition by p."type") cum_ratio 
from 
products p 
) prods 
inner join 
(
select "type", route, nvl (lag (cum_ratio, 1) over (partition by "type" order by route), 0) ratio_start, cum_ratio ratio_end from 
(select "type", route, sum (rr) over (partition by "type" order by route) cum_ratio 
from (select c."type", c.route, ratio_to_report (c.percent) over (partition by "type") rr from clienttable c))) client 
on prods."type" = client."type" 
and prods.cum_ratio >= client.ratio_start and prods.cum_ratio < client.ratio_end 

này cho kết quả sau: -

+----+------+----+ 
| ID | type | CR | 
+----+------+----+ 
| 1 | 1 | A | 
| 2 | 1 | A | 
| 3 | 1 | B | 
| 4 | 1 | B | 
| 5 | 1 | B | 
| 6 | 1 | C | 
| 8 | 2 | A | 
| 9 | 2 | A | 
| 10 | 2 | B | 
| 11 | 2 | B | 
| 13 | 3 | C | 
+----+------+----+ 
0

Làm thế nào về một cái gì đó giống như

--For updating type 1, set every route for type 1 as null. 

UPDATE MyTable 
SET [Route] = null 
WHERE [Type] = '1' 

--Update Route A(40%) 
DECLARE @myVal int; 
SET @myVal =CAST(0.4*(SELECT COUNT(*) FROM myTable WHERE [Type]='1') AS INT); 
WITH tab AS 
    (
    SELECT TOP (@myVal) * 
    FROM myTable 
    ) 
UPDATE tab 
SET  [Route] = 'A' 
WHERE [Route] is null 

--Update Route B (40%) 
DECLARE @myVal int; 
SET @myVal =CAST(0.4*(SELECT COUNT(*) FROM myTable WHERE [Type]='1') AS INT); 
WITH tab AS 
    (
    SELECT TOP (@myVal) * 
    FROM myTable 
    ) 
UPDATE tab 
SET  [Route] = 'B' 
WHERE [Route] is null 


--Update Route C (20%) 
DECLARE @myVal int; 
SET @myVal =CAST(0.2*(SELECT COUNT(*) FROM myTable WHERE [Type]='1') AS INT); 
WITH tab AS 
    (
    SELECT TOP (@myVal) * 
    FROM myTable 
    ) 
UPDATE tab 
SET  [Route] = 'C' 
WHERE [Route] is null 
+0

Có lẽ tôi không nhìn thấy nó, nhưng không phải là điều này vẫn là một bản cập nhật cho mỗi loại cho mỗi tuyến đường mà tôi đã làm? Ngoài ra, bạn có thể "chọn phần trăm X hàng đầu" từ một bảng để bạn có thể bỏ qua các bước đếm. Tôi đang nghĩ giải pháp, nếu có, sẽ là một tuyên bố lớn. – powlette

+0

vâng. nó cập nhật một loại/tuyến cho mỗi câu lệnh cập nhật. – arunlalam

0

Tôi không biết nếu chức năng tương tự tồn tại trong SQL Server. Trong Oracle có mệnh đề SAMPLE. Dưới truy vấn lựa chọn 10% hàng từ một bảng:

SELECT empno 
    FROM scott.emp 
SAMPLE (10) 
/

Sau đó cập nhật của bạn sẽ dễ dàng ... Có lẽ ai lấy cái gì tương tự tồn tại trong SQL Server. Bạn cũng có thể đếm các hàng hoặc dữ liệu rồi calc phần trăm rồi cập nhật ...

+0

Trong phần bình luận, tôi nói rằng chúng ta đang làm điều này trong một vòng lặp: Cập nhật sản phẩm thiết lập tuyến đường = 'A' trong đó type = 1 và id in (chọn top 40% từ các sản phẩm mà type = 1 và route is null) không khó, nhưng tôi muốn giảm số lượng cập nhật. – powlette

0
WITH po AS 
    (SELECT 
     ID, 
     Type, 
     ROW_NUMBER() OVER (PARTITION BY Type 
          ORDER BY ID 
         ) AS Rn, 
     COUNT(*) OVER (PARTITION BY Type) AS CntType 
    FROM 
      Products 
)  
, ro AS 
    (SELECT 
     Type, 
     Route, 
     (SELECT SUM(rr.Percent) 
      FROM Route AS rr 
      WHERE rr.Type = r.Type 
      AND rr.Route <= r.Route 
     ) AS SumPercent 
    FROM 
      Routes AS r 
) 
UPDATE p 
SET p.Route = 
      (SELECT MIN(ro.Route) 
       FROM ro 
       WHERE ro.Type = po.Type 
       AND ro.SumPercent >= po.Rn/po.CntType 
      ) 
FROM Products AS p 
    JOIN 
     po ON po.ID = p.ID ; 
Các vấn đề liên quan