2010-09-09 28 views
5

Tôi đang cố gắng quấn quanh đầu này sáng nay.Câu hỏi hóc búa về SQL, cách chọn ngày mới nhất cho một phần, nhưng chỉ có 1 hàng cho mỗi phần (duy nhất)

Tôi đang cố gắng hiển thị trạng thái inventory cho các bộ phận (đối với sản phẩm của chúng tôi) và truy vấn này chỉ trở nên phức tạp nếu tôi cố gắng trả lại tất cả các phần.

Hãy để tôi đẻ nó ra:

  • bảng duy nhất inventoryReport
  • tôi có một danh sách riêng biệt của các bộ phận X Tôi muốn hiển thị, kết quả trong số đó phải là X # hàng (1 hàng mỗi phần hiển thị mục nhập khoảng không quảng cáo mới nhất).
  • bảng được tạo thành từ các mục nhập ngày của thay đổi khoảng không quảng cáo (vì vậy tôi chỉ cần mục nhập ngày LATEST mỗi phần).
  • tất cả dữ liệu trong bảng đơn này, vì vậy không cần tham gia.

Hiện nay 1 phần duy nhất, nó là khá đơn giản và tôi có thể thực hiện điều này bằng cách làm như sql sau (để cung cấp cho bạn một số ý tưởng):

SELECT  TOP (1) ldDate, ptProdLine, inPart, inSite, inAbc, ptUm, inQtyOh + inQtyNonet AS in_qty_oh, inQtyAvail, inQtyNonet, ldCustConsignQty, inSuppConsignQty 
FROM   inventoryReport 
WHERE  (ldPart = 'ABC123') 
ORDER BY ldDate DESC 

mà được tôi hàng TOP 1 của tôi, vì vậy đơn giản mỗi phần, tuy nhiên tôi cần hiển thị tất cả X (cho phép nói 30 phần). Vì vậy, tôi cần 30 hàng, với kết quả đó. Tất nhiên, giải pháp đơn giản là vòng lặp X # của các cuộc gọi sql trong mã của tôi (nhưng nó sẽ tốn kém) và điều đó là đủ, nhưng với mục đích này, tôi rất thích làm việc với SQL này để giảm x # các cuộc gọi trở lại db (nếu không cần thiết) xuống chỉ 1 truy vấn.

Từ những gì tôi có thể thấy ở đây, tôi cần phải theo dõi ngày mới nhất cho mỗi mục bằng cách nào đó trong khi tìm kiếm tập kết quả của tôi.

tôi cuối cùng sẽ làm một

WHERE ldPart in ('ABC123', 'BFD21', 'AA123', etc) 

để hạn chế những phần tôi cần. Hy vọng rằng tôi đã làm cho câu hỏi của tôi đủ rõ ràng. Hãy cho tôi biết nếu bạn có một ý tưởng. Tôi không thể làm một số DISTINCT vì các hàng không giống nhau, ngày cần phải là mới nhất và tôi cần tối đa X hàng.

Suy nghĩ? Tôi đang mắc kẹt ...

Trả lời

2

EDIT: Hãy chắc chắn để kiểm tra hiệu suất của mỗi giải pháp. Như được chỉ ra trong this question, phương pháp CTE có thể hoạt động tốt hơn bằng ROW_NUMBER.

;with cteMaxDate as (
    select ldPart, max(ldDate) as MaxDate 
     from inventoryReport 
     group by ldPart 
) 
SELECT md.MaxDate, ir.ptProdLine, ir.inPart, ir.inSite, ir.inAbc, ir.ptUm, ir.inQtyOh + ir.inQtyNonet AS in_qty_oh, ir.inQtyAvail, ir.inQtyNonet, ir.ldCustConsignQty, ir.inSuppConsignQty 
    FROM cteMaxDate md 
     INNER JOIN inventoryReport ir 
      on md.ldPart = ir.ldPart 
       and md.MaxDate = ir.ldDate 
5
SELECT * 
    FROM (SELECT i.*, 
     ROW_NUMBER() OVER(PARTITION BY ldPart ORDER BY ldDate DESC) r 
     FROM inventoryReport i 
     WHERE ldPart in ('ABC123', 'BFD21', 'AA123', etc) 
     ) 
    WHERE r = 1 
2

Bạn cần phải tham gia vào một Sub-truy vấn:

SELECT i.ldPart, x.LastDate, i.inAbc 
FROM inventoryReport i 
INNER JOIN (Select ldPart, Max(ldDate) As LastDate FROM inventoryReport GROUP BY ldPart) x 
on i.ldPart = x.ldPart and i.ldDate = x.LastDate