2015-08-12 17 views
7

Tôi có một bảng tạm thời trong SQL server như dưới đâyComplex chọn truy vấn cho SQL Server

╔═══════╦═════════╦══════╦═════════╗ 
║Serial ║ Account ║ Due ║ Balance ║ 
║1  ║ A1  ║ 1000 ║ 3100 ║ 
║2  ║ A1  ║ 1000 ║ 3100 ║ 
║3  ║ A1  ║ 1000 ║ 3100 ║ 
║4  ║ A1  ║ 1000 ║ 3100 ║ 
║1  ║ A2  ║ 100 ║ 3100 ║ 
║2  ║ A2  ║ 100 ║ 3100 ║  
║1  ║ B1  ║ 1000 ║ 1100 ║ 
║2  ║ B1  ║ 1000 ║ 1100 ║ 
║1  ║ B2  ║ 100 ║ 1100 ║ 
║2  ║ B2  ║ 100 ║ 1100 ║ 
╚═══════╩═════════╩══════╩═════════╝ 

Tôi muốn xác định các hàng mà do sẽ được thu thập. A1 và A2 Do sẽ được thu thập từ 3100 và B1 và ​​B2 do sẽ được thu thập từ 1100.

Thứ nhất tôi đã sử dụng tích lũy Do như sau

╔═══════╔═════════╦══════╦════════════╦═════════╦ 
║Serial ║ Account ║ Due ║ Cumulative ║ Balance ║ 
║1  ║ A1  ║ 1000 ║ 1000  ║ 3100 ║ 
║2  ║ A1  ║ 1000 ║ 2000  ║ 3100 ║ 
║3  ║ A1  ║ 1000 ║ 3000  ║ 3100 ║ 
║4  ║ A1  ║ 1000 ║ 4000  ║ 3100 ║ 
║1  ║ A2  ║ 100 ║ 100  ║ 3100 ║ 
║2  ║ A2  ║ 100 ║ 200  ║ 3100 ║ 
║1  ║ B1  ║ 1000 ║ 1000  ║ 1100 ║ 
║2  ║ B1  ║ 1000 ║ 2000  ║ 1100 ║ 
║1  ║ B2  ║ 100 ║ 100  ║ 1100 ║ 
║2  ║ B2  ║ 100 ║ 200  ║ 1100 ║ 
╚═══════╚═════════╩══════╩════════════╩═════════╝ 

Bây giờ tôi muốn chọn hàng sau khi sản lượng

╔═══════╔═════════╦══════╦════════════╦═════════╦ 
║Serial ║ Account ║ Due ║ Cumulative ║ Balance ║ 
║1  ║ A1  ║ 1000 ║ 1000  ║ 3100 ║ 
║2  ║ A1  ║ 1000 ║ 2000  ║ 3100 ║ 
║3  ║ A1  ║ 1000 ║ 3000  ║ 3100 ║ 
║1  ║ A2  ║ 100 ║ 100  ║ 3100 ║ 
║1  ║ B1  ║ 1000 ║ 1000  ║ 1100 ║ 
║1  ║ B2  ║ 100 ║ 100  ║ 1100 ║ 
╚═══════╚═════════╩══════╩════════════╩═════════╩ 

Đây là nơi tôi bị kẹt. Làm thế nào tôi có thể chọn những hàng mà không cần sử dụng con trỏ hoặc vòng lặp. Tất cả tôi muốn làm điều này với lệnh chọn và các chức năng cửa sổ. Cảm ơn.

Giải pháp có thể: Nếu bảng có thể được cập nhật như sau thì vấn đề sẽ được giải quyết.

╔═══════╔═════════╦══════╦═══════════════════╦ 
║Serial ║ Account ║ Due ║ Balance Remaining ║ 
║1  ║ A1  ║ 1000 ║ 3100    ║ 
║2  ║ A1  ║ 1000 ║ 2100    ║ 
║3  ║ A1  ║ 1000 ║ 1100    ║ 
║4  ║ A1  ║ 1000 ║ 100    ║ 
║1  ║ A2  ║ 100 ║ 100    ║ 
║2  ║ A2  ║ 100 ║  0    ║ 
║1  ║ B1  ║ 1000 ║ 1100    ║ 
║2  ║ B1  ║ 1000 ║ 100    ║ 
║1  ║ B2  ║ 100 ║ 100    ║ 
║2  ║ B2  ║ 100 ║  0    ║ 
╚═══════╚═════════╩══════╩═══════════════════╩ 

Các trường hợp Số dư Còn bằng/lớn hơn Do chúng tôi cập nhật nó với sự khác biệt nào khác nó sẽ vẫn như trước đây. Vấn đề là ở đây để cập nhật hàng bằng cách phân vùng giữa A & B.

CẬP NHẬT tôi cung cấp liên kết với dữ liệu mới thiết lập để thể hiện yêu cầu của tôi rõ ràng hơn. new dataset

+0

Phiên bản SQL Server nào? – mellamokb

+0

SQL SERVER 2012 trở lên. – Esty

+0

Vấn đề là ngay cả với các chức năng cửa sổ mạnh mẽ được cung cấp trong SQL Server 2012, không có cách nào tốt để tổng tích lũy có điều kiện. Nói cách khác, đóng góp vào tổng điều kiện dựa trên việc tổng số trước đó có lớn hơn số dư hay không.Một giải pháp dựa trên con trỏ có lẽ sẽ là giải pháp dễ nhất và hiệu quả nhất - tại sao bạn không muốn một giải pháp dựa trên con trỏ? – mellamokb

Trả lời

2

Cuối cùng, giải quyết này với bản cập nhật truy vấn.

UPDATE A 
SET 
A.Balance = @Balance 
, @PreBalance = @Balance 
, @Balance = (CASE WHEN (@Balance IS NULL OR @AccountType <> A.AccountType) 
        THEN 
         CASE WHEN A.Balance - A.Due >= 0 
          THEN A.Balance 
          ELSE A.Balance + A.Due 
         END 
        ELSE 
         CASE WHEN @Balance - A.Due >= 0 AND (@Flag = 1 OR @AccountNO <> A.AccountNO) 
           THEN @Balance 
           ELSE @Balance + A.Due 
         END 
       END) - A.Due 
, A.FLAG = @Flag 
, @AccountNO = CASE WHEN A.Flag = 0 THEN A.AccountNO ELSE 'NoDueFoundForAcc' END 
, @Flag = CASE WHEN @AccountType = A.AccountType 
       THEN 
        CASE WHEN @PreBalance = @Balance 
          THEN 0 
          ELSE 1 
         END 
       ELSE 
        CASE WHEN A.Balance - A.Due >= 0 
          THEN 1 
          ELSE 0 
         END 
       END 
, @AccountType = A.AccountType 
FROM #tempTable A 

SELECT * FROM #tempTable A WHERE A.Flag = 1 
0

Để nhận ra điều này, bạn có thể sử dụng một truy vấn đơn giản như dưới đây:

╔═══════╔═════════╦══════╦════════════╦═════════╦ 
║Serial ║ Account ║ Due ║ Cumulative ║ Balance ║ 
║1  ║ A1  ║ 1000 ║ 1000  ║ 3100 ║ 
║2  ║ A1  ║ 1000 ║ 2000  ║ 3100 ║ 
║3  ║ A1  ║ 1000 ║ 3000  ║ 3100 ║ 
║1  ║ A2  ║ 100 ║ 100  ║ 3100 ║ 
║1  ║ B1  ║ 1000 ║ 1000  ║ 1100 ║ 
║1  ║ B2  ║ 100 ║ 100  ║ 1100 ║ 
╚═══════╚═════════╩══════╩════════════╩═════════╩ 

select Serial,Account,Due,Cumulative,Balance from 
(Select *, row_number() over(Partition by Account, order by serial number desc) as r from Temp) t 
where t.r>1 
+0

Bạn đã nhận được kết quả chính xác ... nhưng bạn không áp dụng bất kỳ logic thực tế nào (chọn hàng cho đến khi tích lũy> số dư). Điều này sẽ dễ dàng bị phá vỡ bởi một tập dữ liệu ví dụ khác. – mellamokb

+0

Đồng ý .. Đối với dữ liệu sau, thiết lập truy vấn này sẽ không hoạt động. [link] (http://pastebin.com/cYAeXfMJ) – Esty

+0

@TanjimRahman Như tôi đã đề cập trong câu trả lời của tôi 'Để nhận được kết quả này ' – DhruvJoshi

1

Rất đơn giản

select * from account 
where (Balance-(Select sum(ac.Due) from account ac where 
ac.SerialNo<=account.SerialNo and ac.Account =account.Account)>0) 

Cập nhật

không có mối quan hệ giữa A1 và A2 mà nói rằng số dư 3100 là để được chia sẻ giữa A1 và A2 và không phải với B1.

Vì vậy, bạn phải chỉ định một số nơi mà a1 và a2 là trên cùng một nhóm
có được lựa chọn gợi ý cho bạn
Add nhóm không có cột trong bạn bảng và đưa ra cùng không cho A1 và A2, cùng không khác cho B1 và B2. Sau đó thêm cột ưu tiên chỉ rõ A1 nên trích đầu tiên do đó nếu số dư trái a2 sẽ nhận được cơ hội

sau đó truy vấn sẽ

SELECT   * 
    FROM   account 
    WHERE 
     (Balance - (SELECT 
         SUM(ac.Due) 
         FROM 
         account ac 
         WHERE 
         (ac.GroupNo = account.GroupNo 
          AND ((ac.Account = account.Account 
            AND (ac.SerialNo <= account.SerialNo) 
           ) 
           OR ac.Prioirty < account.Prioirty 
          ) 
         ) 
        ) > 0) 
+0

Truy vấn của bạn trả về như sau [link] (http://pastebin.com/MnMJqRWN) không phải là kết quả yêu cầu. Chuỗi 2 cho tài khoản A2 và B2 là các hàng giả. – Esty

+0

U r right @ VISHMAY..Tôi chỉ đang nghĩ về nó. Có lẽ tôi không thể đưa ra yêu cầu thực tế của tôi trong bộ dữ liệu. Tôi đang đưa ra một tập hợp dữ liệu mới [link] (http://pastebin.com/mmbnCWb9) – Esty

+0

@Tanjim Rahman truy vấn này cũng có thể trong liên kết đã cho của bạn, nhưng nó sẽ không cung cấp cho bạn hiệu suất vì nó cần phải đi hai cấp trong truy vấn phụ, thay vào đó lấy dữ liệu trong mã và sau đó đếm còn lại và sử dụng thích hợp nếu khác – VISHMAY

Các vấn đề liên quan