Bạn có biết một cách dễ dàng để tạo một bản ghi cho mỗi giờ trong 12 giờ qua không?


12

Tôi có một báo cáo cho thấy số lượng sự kiện trong 12 giờ qua, được nhóm theo giờ. Nghe có vẻ dễ dàng, nhưng điều tôi đang vật lộn là làm thế nào để đưa vào các bản ghi che lấp các khoảng trống.

Dưới đây là bảng ví dụ:

Event
(
  EventTime datetime,
  EventType int
)

Dữ liệu trông như thế này:

  '2012-03-08 08:00:04', 1
  '2012-03-08 09:10:00', 2
  '2012-03-08 09:11:04', 2
  '2012-03-08 09:10:09', 1
  '2012-03-08 10:00:17', 4
  '2012-03-08 11:00:04', 1

Tôi cần tạo một tập kết quả có một bản ghi cho mỗi giờ trong 12 giờ qua, bất kể có sự kiện nào trong giờ đó hay không.

Giả sử thời gian hiện tại là '2012 / 03-08 11:00:00', báo cáo sẽ hiển thị (đại khái):

Hour  EventCount
----  ----------
23    0
0     0
1     0
2     0
3     0
4     0
5     0
6     0
7     0
8     1
9     3
10    1

Tôi đã đưa ra một giải pháp sử dụng một bảng có một bản ghi cho mỗi giờ trong ngày. Tôi đã xoay sở để có được kết quả mà tôi đang tìm kiếm bằng cách sử dụng UNION và một số logic trường hợp phức tạp trong mệnh đề where, nhưng tôi hy vọng ai đó có một giải pháp thanh lịch hơn.

Câu trả lời:


21

Đối với SQL Server 2005+, bạn có thể tạo 12 bản ghi đó rất dễ dàng với vòng lặp là CTE đệ quy. Dưới đây là một ví dụ về CTE đệ quy:

DECLARE @Date DATETIME
SELECT @Date = '20120308 11:00:00'

;WITH Dates AS
(
    SELECT DATEPART(HOUR,DATEADD(HOUR,-1,@Date)) [Hour], 
      DATEADD(HOUR,-1,@Date) [Date], 1 Num
    UNION ALL
    SELECT DATEPART(HOUR,DATEADD(HOUR,-1,[Date])), 
      DATEADD(HOUR,-1,[Date]), Num+1
    FROM Dates
    WHERE Num <= 11
)
SELECT [Hour], [Date]
FROM Dates

Sau đó, bạn chỉ cần tham gia nó với bảng sự kiện của bạn.


2
Tôi tìm thấy điều này ngay sau khi bạn đăng. Giải thích.com / 2009/10/21 / Từ Nó chỉ ra rằng sử dụng CTE cho mục đích này kém hiệu quả hơn bảng được lưu trữ. Điều này có đúng không? Như Nick đã nói, có lẽ không có vấn đề gì trong trường hợp này, nhưng ...
Leigh Riffel

4
Tôi nghĩ rằng nó sẽ tạo ra sự khác biệt với số lượng hàng lớn hơn, nếu bạn cần 12 bản ghi, thì sẽ không có hiệu suất nào đạt được
Lamak

Lamak và @swasheck. Heh ... tôi hơi muộn (mất dấu vết của chủ đề này) trong việc tiếp cận nó nhưng không có vấn đề gì. Xem câu trả lời cuối cùng tôi đã đăng để hỗ trợ cho tuyên bố của tôi ở trên. Và hãy nhớ rằng, tất cả các mã có hiệu ứng tích lũy. Nếu tất cả các mã người viết đã "nhanh hơn" 16 lần, một nửa số bài đăng trên các diễn đàn như thế này sẽ không còn cần thiết nữa. Và, không mất nhiều thời gian hơn (đôi khi ngắn hơn) để viết mã nhanh hơn.
Jeff Moden

10

Bảng kiểm đếm có thể được sử dụng cho những thứ như thế này. Họ có thể rất hiệu quả. Tạo bảng kiểm đếm bên dưới. Tôi đã tạo bảng kiểm đếm chỉ với 24 hàng cho ví dụ của bạn, nhưng bạn có thể tạo bảng với nhiều mục bạn muốn phù hợp với các mục đích khác.

SELECT TOP 24 
        IDENTITY(INT,1,1) AS N
   INTO dbo.Tally
   FROM Master.dbo.SysColumns sc1,
        Master.dbo.SysColumns sc2

--===== Add a Primary Key to maximize performance
  ALTER TABLE dbo.Tally
    ADD CONSTRAINT PK_Tally_N 
        PRIMARY KEY CLUSTERED (N) WITH FILLFACTOR = 100

Tôi giả sử bảng của bạn được gọi là dbo.tblEvents, hãy chạy truy vấn bên dưới. Tôi tin rằng đây là những gì bạn đang tìm kiếm:

SELECT t.n, count(e.EventTime)
FROM dbo.Tally t
LEFT JOIN dbo.tblEvent e  on t.n = datepart(hh, e.EventTime)
GROUP BY t.n
ORDER BY t.n

Tôi tin rằng tín dụng đi đến các liên kết sau, tôi tin rằng đây là nơi đầu tiên tôi bắt gặp điều này:

http://www.sqlservercentral.com/articles/T-Query/62867/

http://www.sqlservercentral.com/articles/T-SQL/74118/


+1 nhưng về mặt ngữ nghĩa, đó là một bảng số, không phải là bảng số liệu.
Aaron Bertrand

1
Một trong những định nghĩa của "Tally" là "To Count". "Bảng Tally" được đặt theo tên của "Tally Stick", đây là một thanh dài, mỏng được sử dụng để đếm.
Jeff Moden

7

Đầu tiên, tôi xin lỗi vì sự chậm trễ trong phản hồi của tôi kể từ những bình luận cuối cùng của tôi.

Chủ đề đưa ra trong các ý kiến ​​rằng sử dụng CTE đệ quy (rCTE từ đây trở đi) chạy đủ nhanh vì số lượng hàng thấp. Trong khi nó có thể xuất hiện theo cách đó, không có gì có thể hơn từ sự thật.

BUILD TALLY BẢNG VÀ CHỨC NĂNG TALLY

Trước khi bắt đầu thử nghiệm, chúng tôi cần xây dựng Bảng Tally vật lý với Chỉ số cụm phù hợp và Chức năng Tally theo kiểu Itzik Ben-Gan. Chúng tôi cũng sẽ thực hiện tất cả những điều này trong TempDB để chúng tôi không vô tình bỏ rơi những món quà của bất kỳ ai.

Đây là mã để xây dựng Bảng Tally và phiên bản sản xuất tuyệt vời của mã Itzik hiện tại của tôi.

--===== Do this in a nice, safe place that everyone has
    USE tempdb
;
--===== Create/Recreate a Physical Tally Table
     IF OBJECT_ID('dbo.Tally','U') IS NOT NULL
        DROP TABLE dbo.Tally
;
     -- Note that the ISNULL makes a NOT NULL column
 SELECT TOP 1000001
        N = ISNULL(ROW_NUMBER() OVER (ORDER BY (SELECT NULL))-1,0)
   INTO dbo.Tally
   FROM      sys.all_columns ac1
  CROSS JOIN sys.all_columns ac2
;
  ALTER TABLE dbo.Tally
    ADD CONSTRAINT PK_Tally PRIMARY KEY CLUSTERED (N)
;
--===== Create/Recreate a Tally Function
     IF OBJECT_ID('dbo.fnTally','IF') IS NOT NULL
        DROP FUNCTION dbo.fnTally
;
GO
 CREATE FUNCTION [dbo].[fnTally]
/**********************************************************************************************************************
 Purpose:
 Return a column of BIGINTs from @ZeroOrOne up to and including @MaxN with a max value of 1 Trillion.

 As a performance note, it takes about 00:02:10 (hh:mm:ss) to generate 1 Billion numbers to a throw-away variable.

 Usage:
--===== Syntax example (Returns BIGINT)
 SELECT t.N
   FROM dbo.fnTally(@ZeroOrOne,@MaxN) t
;

 Notes:
 1. Based on Itzik Ben-Gan's cascading CTE (cCTE) method for creating a "readless" Tally Table source of BIGINTs.
    Refer to the following URLs for how it works and introduction for how it replaces certain loops. 
    http://www.sqlservercentral.com/articles/T-SQL/62867/
    http://sqlmag.com/sql-server/virtual-auxiliary-table-numbers
 2. To start a sequence at 0, @ZeroOrOne must be 0 or NULL. Any other value that's convertable to the BIT data-type
    will cause the sequence to start at 1.
 3. If @ZeroOrOne = 1 and @MaxN = 0, no rows will be returned.
 5. If @MaxN is negative or NULL, a "TOP" error will be returned.
 6. @MaxN must be a positive number from >= the value of @ZeroOrOne up to and including 1 Billion. If a larger
    number is used, the function will silently truncate after 1 Billion. If you actually need a sequence with
    that many values, you should consider using a different tool. ;-)
 7. There will be a substantial reduction in performance if "N" is sorted in descending order.  If a descending 
    sort is required, use code similar to the following. Performance will decrease by about 27% but it's still
    very fast especially compared with just doing a simple descending sort on "N", which is about 20 times slower.
    If @ZeroOrOne is a 0, in this case, remove the "+1" from the code.

    DECLARE @MaxN BIGINT; 
     SELECT @MaxN = 1000;
     SELECT DescendingN = @MaxN-N+1 
       FROM dbo.fnTally(1,@MaxN);

 8. There is no performance penalty for sorting "N" in ascending order because the output is explicity sorted by
    ROW_NUMBER() OVER (ORDER BY (SELECT NULL))

 Revision History:
 Rev 00 - Unknown     - Jeff Moden 
        - Initial creation with error handling for @MaxN.
 Rev 01 - 09 Feb 2013 - Jeff Moden 
        - Modified to start at 0 or 1.
 Rev 02 - 16 May 2013 - Jeff Moden 
        - Removed error handling for @MaxN because of exceptional cases.
 Rev 03 - 22 Apr 2015 - Jeff Moden
        - Modify to handle 1 Trillion rows for experimental purposes.
**********************************************************************************************************************/
        (@ZeroOrOne BIT, @MaxN BIGINT)
RETURNS TABLE WITH SCHEMABINDING AS 
 RETURN WITH
  E1(N) AS (SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
            SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
            SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
            SELECT 1)                                  --10E1 or 10 rows
, E4(N) AS (SELECT 1 FROM E1 a, E1 b, E1 c, E1 d)      --10E4 or 10 Thousand rows
,E12(N) AS (SELECT 1 FROM E4 a, E4 b, E4 c)            --10E12 or 1 Trillion rows                 
            SELECT N = 0 WHERE ISNULL(@ZeroOrOne,0)= 0 --Conditionally start at 0.
             UNION ALL 
            SELECT TOP(@MaxN) N = ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E12 -- Values from 1 to @MaxN
;
GO

Nhân tiện ... lưu ý rằng đã xây dựng Bảng Tally một triệu và một hàng và thêm Chỉ mục cụm vào đó trong khoảng một giây. Hãy thử THAT với một rCTE và xem mất bao lâu! ;-)

XÂY DỰNG MỘT SỐ DỮ LIỆU KIỂM TRA

Chúng tôi cũng cần một số dữ liệu thử nghiệm. Có, tôi đồng ý rằng tất cả các chức năng mà chúng tôi sẽ kiểm tra, bao gồm rCTE, chạy trong một phần nghìn giây hoặc ít hơn chỉ 12 hàng nhưng đó là cái bẫy mà rất nhiều người rơi vào. Chúng ta sẽ nói nhiều hơn về cái bẫy đó sau, nhưng bây giờ, hãy mô phỏng việc gọi mỗi chức năng 40.000 lần, tức là khoảng bao nhiêu lần một số chức năng nhất định trong cửa hàng của tôi được gọi trong 8 ngày. Chỉ cần tưởng tượng có bao nhiêu lần các chức năng như vậy có thể được gọi trong một doanh nghiệp bán lẻ trực tuyến lớn.

Vì vậy, đây là mã để xây dựng 40.000 hàng với ngày ngẫu nhiên, mỗi hàng có Số hàng chỉ dành cho mục đích theo dõi. Tôi đã không dành thời gian để làm cho thời gian cả giờ vì nó không quan trọng ở đây.

--===== Do this in a nice, safe place that everyone has
    USE tempdb
;
--===== Create/Recreate a Test Date table
     IF OBJECT_ID('dbo.TestDate','U') IS NOT NULL
        DROP TABLE dbo.TestDate
;
DECLARE  @StartDate DATETIME
        ,@EndDate   DATETIME
        ,@Rows      INT
;
 SELECT  @StartDate = '2010' --Inclusive
        ,@EndDate   = '2020' --Exclusive
        ,@Rows      = 40000  --Enough to simulate an 8 hour day where I work
;
 SELECT  RowNum       = IDENTITY(INT,1,1)
        ,SomeDateTime = RAND(CHECKSUM(NEWID()))*DATEDIFF(dd,@StartDate,@EndDate)+@StartDate
   INTO dbo.TestDate
   FROM dbo.fnTally(1,@Rows)
;

XÂY DỰNG MỘT SỐ CHỨC NĂNG ĐỂ LÀM 12 GIỜ

Tiếp theo, tôi đã chuyển đổi mã rCTE thành một hàm và tạo 3 hàm khác. Tất cả chúng đều được tạo ra dưới dạng iTVF hiệu suất cao (Hàm nội tuyến có giá trị bảng). Bạn luôn có thể nói vì iTVF không bao giờ có BEGIN trong đó như vô hướng hoặc mTVF (Hàm đa giá trị bảng tuyên bố).

Đây là mã để xây dựng 4 hàm đó ... Tôi đặt tên cho chúng theo phương thức chúng sử dụng chứ không phải những gì chúng làm chỉ để dễ xác định chúng hơn.

--=====  CREATE THE iTVFs
--===== Do this in a nice, safe place that everyone has
    USE tempdb
;
-----------------------------------------------------------------------------------------
     IF OBJECT_ID('dbo.OriginalrCTE','IF') IS NOT NULL
        DROP FUNCTION dbo.OriginalrCTE
;
GO
 CREATE FUNCTION dbo.OriginalrCTE
        (@Date DATETIME)
RETURNS TABLE WITH SCHEMABINDING AS
 RETURN
WITH Dates AS
(
    SELECT DATEPART(HOUR,DATEADD(HOUR,-1,@Date)) [Hour], 
      DATEADD(HOUR,-1,@Date) [Date], 1 Num
    UNION ALL
    SELECT DATEPART(HOUR,DATEADD(HOUR,-1,[Date])), 
      DATEADD(HOUR,-1,[Date]), Num+1
    FROM Dates
    WHERE Num <= 11
)
SELECT [Hour], [Date]
FROM Dates
GO
-----------------------------------------------------------------------------------------
     IF OBJECT_ID('dbo.MicroTally','IF') IS NOT NULL
        DROP FUNCTION dbo.MicroTally
;
GO
 CREATE FUNCTION dbo.MicroTally
        (@Date DATETIME)
RETURNS TABLE WITH SCHEMABINDING AS
 RETURN
 SELECT  [Hour] = DATEPART(HOUR,DATEADD(HOUR,t.N,@Date))
        ,[DATE] = DATEADD(HOUR,t.N,@Date)
   FROM (VALUES (-1),(-2),(-3),(-4),(-5),(-6),(-7),(-8),(-9),(-10),(-11),(-12))t(N)
;
GO
-----------------------------------------------------------------------------------------
     IF OBJECT_ID('dbo.PhysicalTally','IF') IS NOT NULL
        DROP FUNCTION dbo.PhysicalTally
;
GO
 CREATE FUNCTION dbo.PhysicalTally
        (@Date DATETIME)
RETURNS TABLE WITH SCHEMABINDING AS
 RETURN
 SELECT  [Hour] = DATEPART(HOUR,DATEADD(HOUR,-t.N,@Date))
        ,[DATE] = DATEADD(HOUR,-t.N,@Date)
   FROM dbo.Tally t
  WHERE N BETWEEN 1 AND 12
;
GO
-----------------------------------------------------------------------------------------
     IF OBJECT_ID('dbo.TallyFunction','IF') IS NOT NULL
        DROP FUNCTION dbo.TallyFunction
;
GO
 CREATE FUNCTION dbo.TallyFunction
        (@Date DATETIME)
RETURNS TABLE WITH SCHEMABINDING AS
 RETURN
 SELECT  [Hour] = DATEPART(HOUR,DATEADD(HOUR,-t.N,@Date))
        ,[DATE] = DATEADD(HOUR,-t.N,@Date)
   FROM dbo.fnTally(1,12) t
;
GO

XÂY DỰNG KIỂM TRA KIỂM TRA ĐỂ KIỂM TRA CHỨC NĂNG

Cuối cùng nhưng không kém phần quan trọng, chúng ta cần một khai thác thử nghiệm. Tôi làm một kiểm tra cơ bản và sau đó kiểm tra từng chức năng theo một cách giống hệt nhau.

Đây là mã cho khai thác thử nghiệm ...

PRINT '--========== Baseline Select =================================';
DECLARE @Hour INT, @Date DATETIME
;
    SET STATISTICS TIME,IO ON;
 SELECT  @Hour = RowNum
        ,@Date = SomeDateTime
   FROM dbo.TestDate
  CROSS APPLY dbo.fnTally(1,12);
    SET STATISTICS TIME,IO OFF;
GO
PRINT '--========== Orginal Recursive CTE ===========================';
DECLARE @Hour INT, @Date DATETIME
;

    SET STATISTICS TIME,IO ON;
 SELECT  @Hour = fn.[Hour]
        ,@Date = fn.[Date]
   FROM dbo.TestDate td
  CROSS APPLY dbo.OriginalrCTE(td.SomeDateTime) fn;
    SET STATISTICS TIME,IO OFF;
GO
PRINT '--========== Dedicated Micro-Tally Table =====================';
DECLARE @Hour INT, @Date DATETIME
;

    SET STATISTICS TIME,IO ON;
 SELECT  @Hour = fn.[Hour]
        ,@Date = fn.[Date]
   FROM dbo.TestDate td
  CROSS APPLY dbo.MicroTally(td.SomeDateTime) fn;
    SET STATISTICS TIME,IO OFF;
GO
PRINT'--========== Physical Tally Table =============================';
DECLARE @Hour INT, @Date DATETIME
;
    SET STATISTICS TIME,IO ON;
 SELECT  @Hour = fn.[Hour]
        ,@Date = fn.[Date]
   FROM dbo.TestDate td
  CROSS APPLY dbo.PhysicalTally(td.SomeDateTime) fn;
    SET STATISTICS TIME,IO OFF;
GO
PRINT'--========== Tally Function ===================================';
DECLARE @Hour INT, @Date DATETIME
;
    SET STATISTICS TIME,IO ON;
 SELECT  @Hour = fn.[Hour]
        ,@Date = fn.[Date]
   FROM dbo.TestDate td
  CROSS APPLY dbo.TallyFunction(td.SomeDateTime) fn;
    SET STATISTICS TIME,IO OFF;
GO

Một điều cần chú ý trong khai thác thử nghiệm ở trên là tôi chuyển tất cả đầu ra thành các biến "vứt đi". Đó là cố gắng giữ cho các phép đo hiệu suất càng tinh khiết càng tốt mà không có bất kỳ kết quả xiên đĩa hoặc màn hình nào.

MỘT CÁCH THẬN TRỌNG TRÊN THỐNG KÊ

Ngoài ra, một lời cảnh báo cho những người thử nghiệm sẽ ... Bạn KHÔNG ĐƯỢC sử dụng THỐNG KÊ TẬP HỢP khi kiểm tra các hàm vô hướng hoặc mTVF. Nó chỉ có thể được sử dụng một cách an toàn trên các chức năng iTVF giống như các chức năng trong bài kiểm tra này. THỐNG KÊ SET đã được chứng minh là làm cho các hàm SCALAR chạy chậm hơn hàng trăm lần so với thực tế mà không có nó. Vâng, tôi đang cố gắng nghiêng một cối xay gió khác nhưng đó sẽ là một bài viết dài toàn bộ bài viết và tôi không có thời gian cho việc đó. Tôi có một bài viết trên SQLServerCentral.com nói về điều đó nhưng không có ý nghĩa gì trong việc đăng liên kết ở đây vì ai đó sẽ hiểu rõ về nó.

KẾT QUẢ KIỂM TRA

Vì vậy, đây là kết quả thử nghiệm khi tôi chạy thử nghiệm khai thác trên máy tính xách tay i5 nhỏ của tôi với 6GB RAM.

--========== Baseline Select =================================
Table 'Worktable'. Scan count 1, logical reads 82309, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'TestDate'. Scan count 1, logical reads 105, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 203 ms,  elapsed time = 206 ms.
--========== Orginal Recursive CTE ===========================
Table 'Worktable'. Scan count 40001, logical reads 2960000, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'TestDate'. Scan count 1, logical reads 105, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 4258 ms,  elapsed time = 4415 ms.
--========== Dedicated Micro-Tally Table =====================
Table 'Worktable'. Scan count 1, logical reads 81989, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'TestDate'. Scan count 1, logical reads 105, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 234 ms,  elapsed time = 235 ms.
--========== Physical Tally Table =============================
Table 'Worktable'. Scan count 1, logical reads 81989, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'TestDate'. Scan count 1, logical reads 105, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'Tally'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 250 ms,  elapsed time = 252 ms.
--========== Tally Function ===================================
Table 'Worktable'. Scan count 1, logical reads 81989, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'TestDate'. Scan count 1, logical reads 105, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 250 ms,  elapsed time = 253 ms.

"CHỌN BASELINE", chỉ chọn dữ liệu (mỗi hàng được tạo 12 lần để mô phỏng cùng một khối lượng hoàn trả), xuất hiện đúng vào khoảng 1/5 giây. Mọi thứ khác đến vào khoảng một phần tư giây. Vâng, tất cả mọi thứ ngoại trừ chức năng rCTE đẫm máu. Phải mất 4 và 1/4 giây hoặc lâu hơn 16 lần (chậm hơn 1.600%).

Và nhìn vào số lần đọc logic (bộ nhớ IO) ... rCTE đã tiêu thụ một con số khổng lồ 2.960.000 (gần 3 TRIỆU lần đọc) trong khi các chức năng khác chỉ tiêu thụ khoảng 82.100. Điều đó có nghĩa là rCTE tiêu thụ IO nhiều hơn 34,3 lần so với bất kỳ chức năng nào khác.

BỚT TƯ TƯỞNG

Hãy tóm tắt. Phương pháp rCTE để thực hiện điều 12 hàng "nhỏ" này đã sử dụng 16 TIMES (1.600%) CPU (và thời lượng) nhiều hơn và 34.3 TIMES (3.430%) IO bộ nhớ nhiều hơn bất kỳ chức năng nào khác.

Heh ... tôi biết bạn đang nghĩ gì "Thỏa thuận lớn! Nó chỉ là một chức năng."

Vâng, đồng ý, nhưng bạn có bao nhiêu chức năng khác? Bạn có bao nhiêu nơi khác ngoài chức năng? Và bạn có ai trong số những người làm việc với hơn 12 hàng mỗi lần chạy không? Và, có bất kỳ cơ hội nào mà một người nào đó trong một phương thức mua lại có thể sao chép mã rCTE đó cho một cái gì đó lớn hơn nhiều không?

Ok, thời gian để được cùn. Hoàn toàn không có ý nghĩa đối với mọi người để biện minh cho mã bị thách thức hiệu suất chỉ vì số lượng hàng được cho là hạn chế hoặc việc sử dụng. Ngoại trừ khi bạn mua hộp MPP với giá hàng triệu đô la (chưa kể chi phí viết lại mã để hoạt động trên máy đó), bạn không thể mua máy chạy mã nhanh hơn 16 lần (SSD đã thắng Sẽ không làm điều đó ... tất cả những thứ này đều có trong bộ nhớ tốc độ cao khi chúng tôi thử nghiệm nó). Hiệu suất là trong mã. Hiệu suất tốt là trong mã tốt.

Bạn có thể tưởng tượng nếu tất cả các mã của bạn chạy "chỉ" nhanh hơn 16 lần?

Không bao giờ biện minh cho mã xấu hoặc hiệu năng bị thách thức trên số lượng hàng thấp hoặc thậm chí sử dụng thấp. Nếu bạn làm thế, bạn có thể phải mượn một trong những cối xay gió mà tôi bị cáo buộc nghiêng để giữ cho CPU và đĩa của bạn đủ mát. ;-)

MỘT CÔNG VIỆC TRÊN CÔNG VIỆC "TALLY"

Vâng tôi đồng ý. Về mặt ngữ nghĩa, Bảng Tally chứa các số, không phải là "số đo". Trong bài viết gốc của tôi về chủ đề này (nó không phải là bài viết gốc về kỹ thuật nhưng nó là bài viết đầu tiên của tôi về nó), tôi gọi nó là "Tally" không phải vì những gì nó chứa, mà vì những gì nó ... được sử dụng để "đếm" thay vì lặp và "Tally" một cái gì đó là "Đếm" thứ gì đó. ;-) Gọi nó là những gì bạn sẽ ... Bảng số, Bảng kiểm đếm, Bảng tuần tự, bất cứ điều gì. Tôi không quan tâm. Đối với tôi, "Tally" có nghĩa đầy đủ hơn và, là một DBA lười biếng tốt, chỉ chứa 5 chữ cái (2 giống hệt nhau) thay vì 7 và dễ nói hơn với hầu hết mọi người. Nó cũng là "số ít", theo quy ước đặt tên của tôi cho các bảng. ;-) Nó ' Đây cũng là những gì bài báo có chứa một trang từ một cuốn sách từ những năm 60 được gọi là nó. Tôi sẽ luôn gọi nó là "Bảng kiểm đếm" và bạn vẫn sẽ biết ý nghĩa của tôi hoặc người khác. Tôi cũng tránh ký hiệu Hungary như bệnh dịch hạch nhưng gọi hàm này là "fnTally" để tôi có thể nói "Chà, nếu bạn sử dụng Hàm Tally eff-en tôi đã chỉ cho bạn, bạn sẽ không gặp vấn đề về hiệu năng" mà không thực sự là vấn đề Vi phạm nhân sự. ;-) mà không thực sự là một vi phạm nhân sự. ;-) mà không thực sự là một vi phạm nhân sự. ;-)

Điều tôi quan tâm hơn là mọi người học cách sử dụng nó đúng cách thay vì dùng đến những thứ như hiệu suất thách thức các rCTE và các hình thức khác của RBAR ẩn.


2

Bạn sẽ cần RIGHT JOINdữ liệu của mình với truy vấn trả về một bản ghi cho mỗi giờ bạn cần.

Xem điều này cho một vài cách để có được một số hàng mà sau đó bạn có thể trừ đi hàng giờ kể từ thời điểm hiện tại.

Trong Oracle, một truy vấn phân cấp trên kép sẽ tạo ra các hàng:

SELECT to_char(sysdate-level/24,'HH24') FROM dual CONNECT BY Level <=24;

Đó là "truy vấn trả về một bản ghi cho mỗi giờ" mà tôi đang gặp vấn đề. Chỉ cần cố gắng tìm ra cách tạo ra 12 (hoặc 24) bản ghi với mỗi giờ trong 12 (hoặc 24) giờ qua.
datagod
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.