2016-04-07 20 views
1

Bana gelen çalışmaları hakkında genel bir bilgi veren bir sorgu var:saatte başlangıç ​​ve bitiş zamanı ve değere dayalı zaman planı oluşturma

Start    End ToPack 
2016-04-07 10:00  14:00 40 
2016-04-07 16:00  20:00 80 
    ... 

Ben başına 10 ünite paketi zorunda saymak kolaydır saat 16-20 arasında saatte 10-14 ila 20 birim arasında. Böyle bir tabloda sunabilme olmak istiyorum:

TIME  ToPack 
10:00 10 
11:00 10 
12:00 10 
... 
16:00 20 
17:00 20 
... 
etc 

Ben CTE kullanarak ama şimdiye kadar başarısız oldum yapmaya çalışıyorum ...

cevap

3

ben istiyorum table of numbers ve CROSS APPLY kullanın.

Sayı tablosu, 1'den tam sayıya kadar bir sayıya, 100.000'e kadar bir tamsayı sayıları olan bir sütuna sahip bir tablodur. Şahsen 100K numaraları ile tabloyu kullanıyorum. Aaron Bertrand, bu tabloyu nasıl oluşturacağınızı açıklayan bir good article yazdı.

Örnek veri

DECLARE @T TABLE (StartDT datetime2(0), EndDT datetime2(0), ToPack float); 
INSERT INTO @T (StartDT, EndDT, ToPack) VALUES 
('2016-04-07 10:00:00', '2016-04-07 14:00:00', 40), 
('2016-04-07 16:00:00', '2016-04-07 20:00:00', 80); 

@ Vladimir'in mükemmel SOLUT bir varyasyon olarak Sorgu

SELECT * 
FROM 
    @T AS T 
    CROSS APPLY 
    (
     SELECT 
      DATEADD(hour, dbo.Numbers.Number-1, T.StartDT) AS HourDT 
      , T.ToPack/DATEDIFF(hour, T.StartDT, T.EndDT) AS ToPackPerHour 
     FROM dbo.Numbers 
     WHERE dbo.Numbers.Number <= DATEDIFF(hour, T.StartDT, T.EndDT) 
    ) AS CA 
ORDER BY HourDT; 

Sonucu

+---------------------+---------------------+--------+---------------------+---------------+ 
|  StartDT  |  EndDT  | ToPack |  HourDT  | ToPackPerHour | 
+---------------------+---------------------+--------+---------------------+---------------+ 
| 2016-04-07 10:00:00 | 2016-04-07 14:00:00 |  40 | 2016-04-07 10:00:00 |   10 | 
| 2016-04-07 10:00:00 | 2016-04-07 14:00:00 |  40 | 2016-04-07 11:00:00 |   10 | 
| 2016-04-07 10:00:00 | 2016-04-07 14:00:00 |  40 | 2016-04-07 12:00:00 |   10 | 
| 2016-04-07 10:00:00 | 2016-04-07 14:00:00 |  40 | 2016-04-07 13:00:00 |   10 | 
| 2016-04-07 16:00:00 | 2016-04-07 20:00:00 |  80 | 2016-04-07 16:00:00 |   20 | 
| 2016-04-07 16:00:00 | 2016-04-07 20:00:00 |  80 | 2016-04-07 17:00:00 |   20 | 
| 2016-04-07 16:00:00 | 2016-04-07 20:00:00 |  80 | 2016-04-07 18:00:00 |   20 | 
| 2016-04-07 16:00:00 | 2016-04-07 20:00:00 |  80 | 2016-04-07 19:00:00 |   20 | 
+---------------------+---------------------+--------+---------------------+---------------+ 
+0

Parlak! Döngü oluşturmayı denemeye başladım ancak bu çözüm çok daha basit ve hızlı! – Yasskier

0

iyon, ben çok uygun generate_series işlevini kullanarak önerebilirim.

Örnek Veri(metin biçiminde, tam olarak verileri kullanarak):

CREATE TABLE #ToPack (StartDT char(16), EndT char(5), ToPack int); 
INSERT INTO #ToPack VALUES ('2016-04-07 10:00', '14:00', 40); 
INSERT INTO #ToPack VALUES ('2016-04-07 16:00', '20:00', 80); 

Sorgu(siz önerdiği gibi Sonucu):

SELECT SUBSTRING(tp.StartDT, 1, 10) AS [Date], 
     SUBSTRING(CONVERT(varchar(20), s.date_hour, 120), 12, 5) AS TimeSlot, 
     s.ToPackSlot 
FROM (
    SELECT *, CONVERT(datetime, StartDT) AS date_start, 
     CONVERT(datetime, convert(char(11), StartDT)+EndT) AS date_end 
    FROM #ToPack 
) tp 
CROSS APPLY (
    SELECT DATEADD(hour, g.IntValue, tp.date_start) AS date_hour, 
     tp.ToPack/DATEDIFF(hour, tp.date_start, tp.date_end) AS ToPackSlot 
    FROM generate_series(1, DATEDIFF(hour, tp.date_start, tp.date_end), 1) g) s 
+0

Bu "generate_series" işlevi uygun olabilir, ancak satır içi satırları bir WHILE döngüsünde geçici bir tabloya yerleştirmekten çok daha verimli bir şekilde uygulanabilir ve uygulanmalıdır. –

+0

@ Vladimir, "generate_series" sonuçlarının dinamik olması amaçlanmıştır, bu yüzden sonuçta her zaman bir döngü şeklinde üretileceklerdir. TSQL'in geniş döngüler için çok etkili olmadığını doğrulayın. Sunucuda generate_series (1, 1000000, 1) 'den select (*) seçmek için 14 saniye sürdü, ancak kod hemen hemen aynı olsa da, PostgreSQL'de çalıştırılmak üzere 0.3 saniye sürdü. . Bunun gibi küçük takımlar için bu işlevin rahatlığı harikadır, ancak performansı “Numbers” tablosuyla (generate_series() ;-) ile oluşturulabilir) artırılabilir. –

+0

[Bu makale] (http://sqlperformance.com/2013/01/t-sql-queries/generate-a-set-1) tarafından Aaron Bertrand, bir dizi satır oluşturmak için çeşitli yöntemler göstermektedir. T-SQL'de saniyenin bir kesirinde 1M satırları oluşturmanın kesin yolları vardır. Sayı tablosu bunlardan sadece bir tanesidir. –

İlgili konular