2016-05-31 6 views
0

Ich berechne eine kumulative Anzahl (2 vues aus zwei Tabellen). Ich habe das folgende Ergebnis erzielt. Nun möchte ich die NULL-Werte wie folgt ersetzen: Wenn es die erste Zeile der Tabelle ist, dann muss ich stattdessen den ersten Wert nicht Null einfügen. Für den Rest der Zeilen muss ich den letzten Nicht-Null-Wert einfügen, der vor der aktuellen Zeile steht. Gibt es einen Weg, dies zu erreichen?Ersetzen Null Werte mit Daten aus der gleichen Tabelle

Date     | Count1 | Count2 
2016-01-01 00:00:00.000 | NULL | 52 
2016-01-02 00:00:00.000 | NULL | 54 
2016-01-05 00:00:00.000 | 62  | 55 
2016-01-08 00:00:00.000 | NULL | 56 
2016-01-11 00:00:00.000 | 91  | NULL 
2016-01-12 00:00:00.000 | 92  | 59 

Gewünschtes Ergebnis:

Date     | Count1 | Count2 
2016-01-01 00:00:00.000 | 62  | 52 
2016-01-02 00:00:00.000 | 62  | 54 
2016-01-05 00:00:00.000 | 62  | 55 
2016-01-08 00:00:00.000 | 62  | 56 
2016-01-11 00:00:00.000 | 91  | 56 
2016-01-12 00:00:00.000 | 92  | 59 

Die Abfrage, die ich verwendet, um dieses Ergebnis zu erzeugen:

declare @DateCountOpportunities table(d int primary key, c int, cr int) 
insert into @DateCountOpportunities 
select 
     datediff(d, 0, IsNull(CreationDate, StartDate)) as d, 
     count(*) as OpportunitiesCount, 
     0 
     from [JobOpportunities] 
     group by datediff(d, 0, IsNull(CreationDate, StartDate)) 

declare @rt int = 0 
declare @anchor int 

update @DateCountOpportunities set 
     @rt = cr = @rt + c, 
     @anchor = d 
option (maxdop 1) 

declare @DateCountRestaurants table(d int primary key, c int, cr int) 
insert into @DateCountRestaurants 
select 
     datediff(d, 0, CreatedAt) as d, 
     count(*) as RestaurantsCount, 
     0 
from [Restaurants] 
group by datediff(d, 0, CreatedAt) 

declare @rtRes int = 0 
declare @anchorRs int 

update @DateCountRestaurants set 
     @rtRes = cr = @rtRes + c, 
     @anchorRs = d 
option (maxdop 1) 

Declare @ResultTable table(DateOpportunities DateTime, DateRestaurant DateTime, RestaurantsCount int, OpportunitiesCount int) 
insert into @ResultTable 

select isnull(DateOpportunities, DateRestaurants) DateOpportunities, isnull(DateRestaurants, DateOpportunities) DateRestaurant, RestaurantsCount, OpportunitiesCount from 
(
    select 
      dateadd(d, d, 0) as DateRestaurants, 
      cr as RestaurantsCount 
    from @DateCountRestaurants 

) Rs 

full outer join 
(
    select 
      dateadd(d, d, 0) as DateOpportunities, 
      cr as OpportunitiesCount 
    from @DateCountOpportunities 

)Opp 
on Rs.DateRestaurants = Opp.DateOpportunities 
order by DateOpportunities 


select DateOpportunities as [Date], 
RestaurantsCount 
, 
OpportunitiesCount from @ResultTable 
+5

Dies sieht aus wie die Art der Sache, die besser gelöst ist durch das Modifizieren ursprüngliche Abfrage, die das Ergebnis erzeugt, anstatt das, was hier gezeigt wird, als gegeben zu nehmen und sich darüber zu stapeln. Was sind deine Basisdaten und was ist deine aktuelle Abfrage? –

+0

Wenn Sie eine kumulative Zählung durchführen, glaube ich, dass Ihre Antwort in der Abfrage liegt, mit der die von Ihnen angezeigte Ausgabe generiert wird. Was Sie tun möchten, ist möglich, könnte aber kompliziert werden und ist wahrscheinlich nicht notwendig. Können Sie diese Abfrage posten? –

+0

@ JeroenMostert es ist eine komplizierte Abfrage, das Problem ist, dass ich die kumulative Anzahl von zwei separaten Tabellen bekomme. Ich werde die Abfrage veröffentlichen, wenn Sie wollen – Kira

Antwort

1

Das ist ein bisschen einer gehetzten Antwort, aber ich hoffe, es hilft immer noch. Die folgende Abfrage aktualisiert alle Datensätze nur für eine Spalte. Daher müssen Sie möglicherweise die Logik für die zweite Spalte wiederholen. Es gibt wahrscheinlich auch eine Möglichkeit, diese Logik so zu ändern, dass sie sowohl Count1 als auch Count2 innerhalb der gleichen Abfrage behandelt (d. H. Nicht mehrere UPDATE-Anweisungen benötigt), aber ich habe momentan nicht genug Zeit, um diese Lösung durchzuarbeiten.

Ich habe die folgenden Situationen getestet, wo die NULL in der ersten Reihe ist (s), Mittelreihen und in der letzten Reihe mit Erfolg:

CREATE TABLE #counting ([Date] DATETIME, Count1 INT, Count2 INT) 
INSERT INTO #counting 
SELECT '2016-01-01', NULL, 52 UNION 
SELECT '2016-01-02', NULL, 54 UNION 
SELECT '2016-01-05', 62, 55 UNION 
SELECT '2016-01-08', NULL, 56 UNION 
SELECT '2016-01-11', 91, NULL UNION 
SELECT '2016-01-12', 92, 59 UNION 
SELECT '2016-01-13', NULL, 56 


UPDATE 
    #counting 
SET 
    Count1 = rangeValue 
FROM 
    (
    SELECT * FROM 
    (
     SELECT TOP 1 
     firstDate, 
     firstValue.[Date] AS lastDate, 
     firstValue.Count1 AS rangeValue 
     FROM 
     #counting AS firstValue, 
     (SELECT MIN([Date]) AS firstDate FROM #counting WHERE Count1 IS NULL) AS firstDate 
     WHERE 
     Count1 IS NOT NULL AND 
     firstDate < firstValue.[Date] 
     ORDER BY 
     [Date] 
    ) AS a 
    UNION 
    SELECT 
     firstValueRecord.[Date] AS firstDate, 
     lastNullRecord.[Date] AS lastDate, 
     MAX(firstValueRecord.Count1) AS rangeValue 
    FROM 
     #counting AS firstValueRecord, 
     #counting AS nonNullRecords, 
     #counting AS lastNullRecord 
    WHERE 
     firstValueRecord.Count1 IS NOT NULL AND 
     nonNullRecords.Count1 IS NOT NULL AND 
     lastNullRecord.Count1 IS NULL AND 
     lastNullRecord.[Date] > nonNullRecords.[Date] AND 
     nonNullRecords.[Date] >= firstValueRecord.[Date] 
    GROUP BY 
     lastNullRecord.[Date], 
     firstValueRecord.[Date] 
    HAVING 
     COUNT(DISTINCT nonNullRecords.[Date]) = 1 
) AS a 
WHERE 
    Count1 IS NULL AND 
    [Date] BETWEEN firstDate AND lastDate 
0

Beginnend mit SQL Server 2012 wir SUM()OVER(... ORDER BY ...) verwenden können um laufende Summen zu berechnen. Beispiel:

SELECT *, SUM(t.Amount) OVER(ORDER BY t.ActionDate) AS RunningTotal 
FROM (VALUES 
    ('2016-01-01 00:00:00.000', 62), 
    ('2016-01-02 00:00:00.000', 0), 
    ('2016-01-05 00:00:00.000', 0), 
    ('2016-01-08 00:00:00.000', 0), 
    ('2016-01-11 00:00:00.000', 29), 
    ('2016-01-12 00:00:00.000', 0) 
) t(ActionDate, Amount) 

Ergebnisse:

ActionDate    Amount  RunningTotal 
----------------------- ----------- ------------ 
2016-01-01 00:00:00.000 62   62 
2016-01-02 00:00:00.000 0   62 
2016-01-05 00:00:00.000 0   62 
2016-01-08 00:00:00.000 0   62 
2016-01-11 00:00:00.000 29   91 
2016-01-12 00:00:00.000 0   91 

Das bedeutet, dass die erste T-SQL-Batch kann somit vereinfacht werden:

SELECT 
    ISNULL(b.ActionDate, d.ActionDate) AS ActionDate, 
    b.RunningTotal1, 
    d.RunningTotal2 
FROM 
(
    SELECT b.ActionDate, SUM(b.Amount) OVER(ORDER BY b.ActionDate) AS RunningTotal1 
    FROM (
     SELECT t.ActionDate, SUM(t.Amount) AS Amount 
     FROM dbo.FirstTable t 
     GROUP BY t.ActionDate 
     UNION ALL 
     SELECT DISTINCT t.ActionDate, NULL AS Amount 
     FROM dbo.SeconTable t 
     WHERE NOT EXISTS (SELECT * FROM dbo.FirstTable x WHERE x.ActionDate = t.ActionDate) 
    ) a 
) AS b 
INNER JOIN 
(
    SELECT d.ActionDate, SUM(d.Amount) OVER(ORDER BY d.ActionDate) AS RunningTotal2 
    FROM (
     SELECT DISTINCT t.ActionDate, NULL AS Amount 
     FROM dbo.FirstTable t 
     WHERE NOT EXISTS (SELECT * FROM dbo.SecondTable x WHERE x.ActionDate = t.ActionDate) 
     UNION ALL 
     SELECT t.ActionDate, SUM(t.Amount) AS Amount 
     FROM dbo.SeconTable t 
     GROUP BY t.ActionDate 
    ) c 
) AS d 
ON b.ActionDate = d.ActionDate 
+0

Hinweis: Ich habe diese Lösung nicht getestet. –

Verwandte Themen