Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Tìm tổng thời gian đã làm việc với nhiều công việc / đơn đặt hàng có thời gian trùng lặp / chồng chéo trên mỗi công nhân và công việc / đơn đặt hàng

Truy vấn này cũng thực hiện công việc. Hiệu suất của nó rất tốt (trong khi kế hoạch thực thi trông không quá tuyệt vời, CPU và IO thực tế đã đánh bại nhiều truy vấn khác).

Xem nó hoạt động trong Sql Fiddle .

WITH Times AS (
   SELECT DISTINCT
      H.WorkerID,
      T.Boundary
   FROM
      dbo.JobHistory H
      CROSS APPLY (VALUES (H.JobStart), (H.JobEnd)) T (Boundary)
), Groups AS (
   SELECT
      WorkerID,
      T.Boundary,
      Grp = Row_Number() OVER (PARTITION BY T.WorkerID ORDER BY T.Boundary) / 2
   FROM
      Times T
      CROSS JOIN (VALUES (1), (1)) X (Dup)
), Boundaries AS (
   SELECT
      G.WorkerID,
      TimeStart = Min(Boundary),
      TimeEnd = Max(Boundary)
   FROM
      Groups G
   GROUP BY
      G.WorkerID,
      G.Grp
   HAVING
      Count(*) = 2
)
SELECT
   B.WorkerID,
   WorkedMinutes = Sum(DateDiff(minute, 0, B.TimeEnd - B.TimeStart))
FROM
   Boundaries B
WHERE
   EXISTS (
      SELECT *
      FROM dbo.JobHistory H
      WHERE
         B.WorkerID = H.WorkerID
         AND B.TimeStart < H.JobEnd
         AND B.TimeEnd > H.JobStart
   )
GROUP BY
   WorkerID
;

Với chỉ mục được phân nhóm trên WorkerID, JobStart, JobEnd, JobID và với mẫu 7 hàng ở trên tạo ra một mẫu cho dữ liệu công nhân / công việc mới được lặp lại đủ lần để tạo ra một bảng có 14.336 hàng, đây là kết quả hiệu suất. Tôi đã bao gồm các câu trả lời hiệu quả / đúng đắn khác trên trang (cho đến nay):

Author  CPU  Elapsed  Reads   Scans
------  ---  -------  ------  -----
  Erik  157    166      122       2
Gordon  375    378    106964  53251

Tôi đã thực hiện một bài kiểm tra toàn diện hơn từ một máy chủ khác (chậm hơn) (trong đó mỗi truy vấn được chạy 25 lần, giá trị tốt nhất và kém nhất cho mỗi chỉ số bị loại bỏ và 23 giá trị còn lại được tính trung bình) và nhận được kết quả như sau:

Query     CPU   Duration  Reads   Notes
--------  ----  --------  ------  ----------------------------------
Erik 1    215   231       122     query as above
Erik 2    326   379       116     alternate technique with no EXISTS
Gordon 1  578   682       106847  from j
Gordon 2  584   673       106847  from dbo.JobHistory

Kỹ thuật thay thế mà tôi nghĩ chắc chắn sẽ cải thiện mọi thứ. Chà, nó đã lưu được 6 lần đọc, nhưng tốn nhiều CPU hơn (điều đó có ý nghĩa). Thay vì thực hiện thông qua số liệu thống kê đầu / cuối của mỗi bảng thời gian cho đến cuối, tốt nhất chỉ cần tính toán lại các lát nào cần giữ với EXISTS so với dữ liệu ban đầu. Có thể là một hồ sơ khác nhau của một vài công nhân với nhiều công việc có thể thay đổi thống kê hiệu suất cho các truy vấn khác nhau.

Trong trường hợp có ai muốn thử, hãy sử dụng CREATE TABLEINSERT câu lệnh từ fiddle của tôi và sau đó chạy điều này 11 lần:

INSERT dbo.JobHistory
SELECT
   H.JobID + A.MaxJobID,
   H.WorkerID + A.WorkerCount,
   DateAdd(minute, Elapsed + 45, JobStart),
   DateAdd(minute, Elapsed + 45, JobEnd)
FROM
   dbo.JobHistory H
   CROSS JOIN (
      SELECT
         MaxJobID = Max(JobID),
         WorkerCount = Max(WorkerID) - Min(WorkerID) + 1,
         Elapsed = DateDiff(minute, Min(JobStart), Min(JobEnd))
      FROM dbo.JobHistory
   ) A
;

Tôi đã xây dựng hai giải pháp khác cho truy vấn này nhưng giải pháp tốt nhất có hiệu suất gấp đôi có một lỗ hổng nghiêm trọng (không xử lý chính xác các phạm vi thời gian hoàn toàn kèm theo). Cái kia có số liệu thống kê rất cao / xấu (tôi biết nhưng phải thử).

Giải thích

Sử dụng tất cả thời gian của điểm cuối từ mỗi hàng, tạo một danh sách riêng biệt về tất cả các phạm vi thời gian có thể được quan tâm bằng cách sao chép từng thời gian của điểm cuối và sau đó nhóm theo cách để ghép nối mỗi lần với thời gian có thể tiếp theo. Tính tổng số phút đã trôi qua của các phạm vi này ở bất kỳ nơi nào chúng trùng với thời gian làm việc thực tế của bất kỳ công nhân nào.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Ngoại lệ 0x80040154 được tạo trong khi thực thi một gói ssis đơn giản trong môi trường MS SQL 2008R2

  2. Làm cách nào để thêm khóa chính auto_increment trong cơ sở dữ liệu SQL Server?

  3. Triển khai quan hệ một-không-một trong SQL Server

  4. Làm cách nào để tạo DSN theo chương trình?

  5. Tự tham chiếu các ràng buộc khóa ngoại và xóa