Son 12 saatin her saati için bir kayıt oluşturmanın kolay bir yolunu biliyor musunuz?


12

Son 12 saat içindeki olay sayısını saate göre gruplandırılmış olarak gösteren bir raporum var. Kulağa yeterince kolay geliyor, ama mücadele ettiğim şey boşlukları kapsayan kayıtların nasıl dahil edileceğidir.

İşte bir örnek tablo:

Event
(
  EventTime datetime,
  EventType int
)

Veriler şöyle görünür:

  '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

Son 12 saatin her saati için bir kayıt içeren bir sonuç kümesi oluşturmam gerekiyor, o saatteki olaylar olsun veya olmasın.

Şu anki saatin '2012-03-08 11:00:00' olduğu varsayıldığında, rapor (kabaca) şunu gösterir:

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

Günün her saati için bir kaydı olan bir tablo kullanan bir çözüm buldum. Bir sendika ve aradığımız durum mantığında kıvrımlı bir vaka mantığı kullanarak aradığım sonuçları elde etmeyi başardım, ama birisinin daha şık bir çözümü olmasını umuyordum.

Yanıtlar:


21

SQL Server 2005+ için, bu 12 kaydı bir özyinelemeli CTE ile çok kolay bir şekilde oluşturabilirsiniz. İşte özyinelemeli bir CTE örneği:

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

Sonra sadece etkinlik masanıza katılmak için nedd.


2
Bunu gönderdikten hemen sonra buldum. explainextended.com/2009/10/21/… Bu amaçla bir CTE kullanmanın depolanan bir tablodan daha az verimli olduğunu gösterir. Bu doğru mu? Nick'in söylediği gibi, muhtemelen bu dava için önemli değil, ama ...
Leigh Riffel

4
Sanırım daha fazla sayıda satırla bir fark yaratacaktır, eğer 12 kayda ihtiyacınız varsa, o zaman hiç performans olmayacak
Lamak

Lamak ve swasheck. Heh ... Biraz geç kaldım (bu ipliğin izini kaybettim) ama sorun değil. Yukarıda iddialarımı desteklemek için nihayet yayınladığım yanıta bakın. Ve unutmayın, tüm kodlar kümülatif bir etkiye sahiptir. Eğer tüm kod yazarları "sadece" 16 kat daha hızlı olsaydı, bunun gibi forumlarda yayınların yarısı artık gerekli olmayacaktı. Daha hızlı kod yazmak artık (bazen daha kısa) sürmez.
Jeff Moden

10

Tally tabloları bu gibi şeyler için kullanılabilir. Çok verimli olabilirler. Aşağıdaki hesap tablosunu oluşturun. Örneğiniz için yalnızca 24 satır içeren hesap çizelgesini oluşturdum, ancak başka amaçlara uyacak şekilde çoğunuzla oluşturabilirsiniz.

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

Tablonuzun dbo.tblEvents olarak adlandırıldığını varsaydım, aşağıdaki sorguyu çalıştırın. Aradığın şey olduğuna inanıyorum:

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

Kredi aşağıdaki bağlantılara gidiyor inanıyorum, ben bu ilk rastlamak bu olduğuna inanıyorum:

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

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


+1 ama anlamsal olarak bu bir sayılar tablosu, bir hesap tablosu değil.
Aaron Bertrand

1
"Tally" nin tanımlarından biri "Saymak" tır. "Tally Table" adını saymak için kullanılan uzun, sıska bir sopa olan "Tally Stick" denir.
Jeff Moden

7

İlk olarak, son yorumlarımdan bu yana verdiğim yanıtın gecikmesinden dolayı özür dilerim.

Konu, yinelenen CTE (buradan itibaren rCTE) kullanılmasının, düşük satır sayısı nedeniyle yeterince hızlı çalıştığı yorumlarında ortaya çıktı. Bu şekilde görünse de, gerçeklerden başka hiçbir şey olamaz.

TALLY MASA VE TALLY FONKSİYONU İNŞA ET

Teste başlamadan önce, uygun Kümelenmiş Endeks ve Itzik Ben-Gan tarzı Tally Fonksiyonu ile fiziksel bir Tally Table oluşturmamız gerekiyor. Bunların hepsini TempDB'de de yapacağız, böylece kimsenin güzelliklerini yanlışlıkla düşürmüyoruz.

Tally Table'ı ve Itzik'in harika kodunun şu anki üretim versiyonunu oluşturmak için kod.

--===== 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

Bu arada ... bir milyon ve bir sıra Tally Table inşa ettiğine ve yaklaşık bir saniye içinde Kümelenmiş Endeks eklediğine dikkat edin. Bunu bir rCTE ile deneyin ve ne kadar sürdüğünü görün! ;-)

BAZI TEST VERİLERİ İNŞA ET

Ayrıca bazı test verilerine ihtiyacımız var. Evet, rCTE dahil olmak üzere test edeceğimiz tüm işlevlerin yalnızca 12 satır için milisaniye veya daha kısa sürede çalıştığını kabul ediyorum, ancak bu birçok insanın düştüğü tuzak. Daha sonra bu tuzak hakkında daha fazla konuşacağız, ancak şimdilik, her bir işlevi 40.000 kez çağırmayı simüle edelim, bu da mağazamdaki belirli işlevlerin 8 saatlik bir günde kaç kez çağrıldığıyla ilgili. Sadece büyük bir çevrimiçi perakende sektöründe bu tür fonksiyonların kaç kez çağrılabileceğini hayal edin.

Dolayısıyla, her biri yalnızca izleme amaçlı bir Satır Numarasına sahip olan rastgele tarihlerle 40.000 satır oluşturmak için kod. Bütün saatler için zaman ayırmadım çünkü burada önemli değil.

--===== 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)
;

12 SATIR SAATİNİ YAPMAK İÇİN BAZI FONKSİYONLAR İNŞA ET

Daha sonra, rCTE kodunu bir fonksiyona dönüştürdüm ve 3 başka fonksiyon oluşturdum. Hepsi yüksek performanslı iTVF'ler (Satır İçi Tablo Değerli İşlevler) olarak oluşturulmuştur. Her zaman söyleyebilirsiniz çünkü iTVF'lerde Skaler veya mTVF'ler (Çoklu Tablo Tablosu Değerli Fonksiyonlar) gibi bir BEGIN yoktur.

İşte bu 4 işlevi oluşturmak için kod ... Ben sadece onları tanımlamak kolaylaştırmak için yaptıkları değil, kullandıkları yöntemden sonra onları adlandırdı.

--=====  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

FONKSİYONLARI TEST ETMEK İÇİN TEST DEMETİ OLUŞTURUN

Son olarak, bir test kayışına ihtiyacımız var. Bir taban çizgisi kontrolü yapıyorum ve sonra her işlevi aynı şekilde test ediyorum.

İşte test kayışının kodu ...

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

Yukarıdaki test kayışında dikkat edilmesi gereken bir şey, tüm çıktıları "tek kullanımlık" değişkenlere çevirmektir. Bu, performans ölçümlerini diske veya ekran bükülme sonuçlarına herhangi bir çıktı olmadan mümkün olduğunca saf tutmaya çalışmaktır.

SET İSTATİSTİKLERİ İLE İLGİLİ DİKKAT SORUNU

Ayrıca, test kullanıcıları için bir uyarı ... Skalar veya mTVF fonksiyonlarını test ederken SET STATISTICS'i KULLANMAMALISINIZ. Sadece bu testteki gibi iTVF fonksiyonlarında güvenle kullanılabilir. SET İSTATİSTİKLERİ SCALAR işlevlerinin onsuz olduğundan yüzlerce kez daha yavaş çalıştığı kanıtlanmıştır. Evet, başka bir yel değirmeni yatırmaya çalışıyorum ama bu daha çok makale şeklinde bir yazı olacak ve bunun için vaktim yok. SQLServerCentral.com hakkında tüm bu konu hakkında bir makale var ama burada bağlantı gönderme bir anlamı yok çünkü biri tüm bu konuda şekil dışarı bükülmüş olacak.

TEST SONUÇLARI

İşte, 6 GB RAM ile küçük i5 dizüstü bilgisayarımda test kayışını çalıştırdığımda test sonuçları.

--========== 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.

Yalnızca verileri seçen "BASELINE SELECT" (her satır aynı getiri hacmini simüle etmek için 12 kez oluşturuldu), saniyenin 1 / 5'i kadar sağa geldi. Diğer her şey saniyenin çeyreğinde geldi. Bu kanlı rCTE işlevi hariç her şey. 4 ve 1/4 saniye veya 16 kat daha uzun sürdü (% 1.600 daha yavaş).

Ve mantıksal okumalara bakın (bellek IO) ... rCTE bir okkalı 2.960.000 (neredeyse 3 MİLYON okuma) tüketirken, diğer fonksiyonlar sadece yaklaşık 82.100 tüketdi. Bu, rCTE'nin diğer işlevlerden 34.3 kat daha fazla bellek IO tüketdiği anlamına gelir.

KAPANIŞ DÜŞÜNCELERİ

Özetleyelim. Bu "küçük" 12 sıralı şeyi yapmak için rCTE yöntemi, diğer işlevlerden daha fazla 16 TIMES (% 1,600) daha fazla CPU (ve süre) ve 34,3 TIMES (% 3,430) daha fazla bellek G / Ç kullanmıştır.

Heh ... Ne düşündüğünü biliyorum. "Büyük Anlaşma! Bu sadece bir işlev."

Evet, kabul ettiniz, ama başka kaç fonksiyonunuz var? Fonksiyonların dışında başka kaç yer var? Ve her biri sadece 12'den fazla satır ile çalışanlarınız var mı? Ve bir yöntem için zor durumda olan birinin bu rCTE kodunu çok daha büyük bir şey için kopyalaması ihtimali var mı?

Tamam, künt olma zamanı. İnsanların, yalnızca sınırlı satır sayısı veya kullanımı nedeniyle performansı zorlayan kodu haklı çıkarması kesinlikle mantıklı değildir. Belki de milyonlarca dolar için bir MPP kutusu satın aldığınızda (böyle bir makinede çalışmasını sağlamak için yeniden kod yazmanın masrafından bahsetmiyorum), kodunuzu 16 kat daha hızlı çalıştıran bir makineyi satın alamazsınız (SSD'ler kazanıldı Bunu da yapmayın ... test ettiğimizde tüm bu şeyler yüksek hızlı bellekteydi). Performans kodda. İyi performans iyi koddadır.

Kodunuzun 16 kat daha hızlı çalıştığını hayal edebiliyor musunuz?

Düşük satır sayılarında ve hatta düşük kullanımda asla kötü veya performansa meydan okuyan kodu gerekçelendirmeyin. Bunu yaparsanız, CPU'larınızı ve disklerinizi yeterince serin tutmak için yatırıldığım yel değirmenlerinden birini ödünç almanız gerekebilir. ;-)

"TALLY" KELİMESİ

Evet katılıyorum. Anlamsal olarak, Tally Table sayıları içerir, "tallies" değil. Konuyla ilgili orijinal makalemde (teknikle ilgili orijinal makale değildi, ancak benim ilk yazım oldu), içerdiği şeyden değil, ne yaptığından dolayı "Tally" dedim ... döngü yerine "saymak" ve bir şey "saymak" için kullanılır. ;-) Ne istediğinizi söyleyin ... Sayılar Tablosu, Tally Tablosu, Sıra Tablosu, neyse Umurumda değil. Benim için, "Tally" daha fazla anlamlıdır ve iyi bir tembel DBA olmak, 7 yerine sadece 5 harf (2 aynıdır) içerir ve çoğu insan için söylemek daha kolaydır. Ayrıca tablolar için adlandırma kuralımı izleyen "tekil" dir. ;-) O' Ayrıca 60'lı yıllardan bir kitaptan bir sayfa içeren makaleye ne denir. Ben her zaman bir "Tally Table" olarak bahsedeceğim ve hala benim ya da bir başkasının ne anlama geldiğini bileceksiniz. Ayrıca veba gibi Macar Notasyonundan da kaçınıyorum ama "fnTally" işlevini çağırdım. İK ihlali. ;-) gerçekte İK ihlali olmadan. ;-) gerçekte İK ihlali olmadan. ;-)

Daha endişe duyduğum şey, performansa meydan okuyan rCTE'ler ve diğer Gizli RBAR formlarına başvurmak yerine onu düzgün kullanmayı öğrenen insanlar.


2

İhtiyacınız olan RIGHT JOINher saat için bir kayıt döndüren bir sorgu ile verilerinize ihtiyacınız olacaktır.

Daha sonra geçerli saatten saat olarak çıkarabileceğiniz bir satır numarası almanın birkaç yolu için bunu görün .

Oracle'da ikili üzerinde hiyerarşik bir sorgu satır oluşturur:

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

Sorun yaşıyorum "her saat için bir kayıt döndüren sorgu" dır. Sadece son 12 (veya 24) saatin her saatinde 12 (veya 24) kayıt oluşturmanın bir yolunu bulmaya çalışmak.
datagod
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.