2017-03-29 22 views
1

ich eine Tabelle in einer SQL Server-Datenbank ein Benutzer lädt ein Bild aus meiner app ein Register jeder Zeit enthält, so TBL_Downloads meine Tabelle hat die folgende Struktur:Count Register für Tag einschließlich Null

UserID| ImageID | DownloadDate    | 
------+-----------+---------------------------+ 
    292 | 782 | 02-01-2016 14:20:22.737 | 
    292 | 783 | 02-01-2016 14:20:22.737 | 
    292 | 784 | 02-02-2016 14:20:22.737 | 
    292 | 785 | 02-04-2016 14:20:22.737 | 
    292 | 786 | 02-05-2016 14:20:22.737 | 
    292 | 787 | 02-06-2016 14:20:22.737 | 

In Tabelle Es werden nur Register für einen bestimmten Benutzer angezeigt, auch wenn es mehrere gibt, um das Beispiel zu vereinfachen.

Was ich möchte, ist eine Ergebnistabelle, die die Anzahl der Downloads für einen bestimmten Benutzer von BY DAY in den letzten 30 Tagen enthält, einschließlich einer Null für die Tage, an denen kein Download stattfand. Im Moment habe ich die folgende Abfrage:

SELECT COUNT(*) AS Downloads 
FROM TBL_Downloads 
WHERE DownloadDate BETWEEN DATEADD(day, -30, GETDATE()) AND GETDATE() 
    AND IdUser = 292 
GROUP BY CAST(DownloadDate AS DATE) 

Diese eine Tabelle mit der Summe zurückgibt, sondern nur für Tage, für die es mindestens einen Eintrag eines Downloads ist.

Haben Sie eine Idee, wie kann ich das lösen?

Antwort

2

Sie können eine Kalender- oder Datums-Tabelle für diese Art von Sache verwenden.

Für nur 152kb im Speicher, können Sie 30 Jahre Daten in einer Tabelle haben mit diesem:

/* dates table */ 
declare @fromdate date = '20000101'; 
declare @years int = 30; 
/* 30 years, 19 used data pages ~152kb in memory, ~264kb on disk */ 
;with n as (select n from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) t(n)) 
select top (datediff(day, @fromdate,dateadd(year,@years,@fromdate))) 
    [Date]=convert(date,dateadd(day,row_number() over(order by (select 1))-1,@fromdate)) 
into dbo.Dates 
from n as deka cross join n as hecto cross join n as kilo 
       cross join n as tenK cross join n as hundredK 
order by [Date]; 
create unique clustered index ix_dbo_Dates_date 
    on dbo.Dates([Date]); 

Ohne den eigentlichen Schritt der Erstellung einer Tabelle zu nehmen, können Sie es in einem common table expression verwenden mit nur diese :

declare @fromdate date = dateadd(day , datediff(day , 0, getdate())-30 , 0); 
declare @thrudate date = dateadd(day , datediff(day , 0, getdate()), 0); 
;with n as (select n from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) t(n)) 
, dates as (
    select top (datediff(day, @fromdate, @thrudate)+1) 
     [Date]=convert(date,dateadd(day,row_number() over(order by (select 1))-1,@fromdate)) 
    from n as deka cross join n as hecto cross join n as kilo 
       cross join n as tenK cross join n as hundredK 
    order by [Date] 
) 
select [Date] 
from dates; 

Verwenden Sie entweder wie so:

select 
    d.Date 
    , count(t.DownloadDate) as DownloadCount 
from dates d 
    left join TBL_Downloads t 
    on d.date = convert(date,t.DownloadDate) 
    and t.userid = 292 
where d.date >= dateadd(day , datediff(day , 0, getdate())-30 , 0) 
    and d.date <= dateadd(day , datediff(day , 0, getdate()), 0) 
group by d.date 

rextester Demo: http://rextester.com/ISK37732 (Daten geändert innerhalb der letzten 30 Tage sein)

kehrt:

+------------+---------------+ 
| Date | DownloadCount | 
+------------+---------------+ 
| 2017-02-27 |    0 | 
| 2017-02-28 |    0 | 
| 2017-03-01 |    2 | 
| 2017-03-02 |    1 | 
| 2017-03-03 |    0 | 
| 2017-03-04 |    1 | 
| 2017-03-05 |    1 | 
| 2017-03-06 |    1 | 
| 2017-03-07 |    0 | 
| 2017-03-08 |    0 | 
| 2017-03-09 |    0 | 
| 2017-03-10 |    0 | 
| 2017-03-11 |    0 | 
| 2017-03-12 |    0 | 
| 2017-03-13 |    0 | 
| 2017-03-14 |    0 | 
| 2017-03-15 |    0 | 
| 2017-03-16 |    0 | 
| 2017-03-17 |    0 | 
| 2017-03-18 |    0 | 
| 2017-03-19 |    0 | 
| 2017-03-20 |    0 | 
| 2017-03-21 |    0 | 
| 2017-03-22 |    0 | 
| 2017-03-23 |    0 | 
| 2017-03-24 |    0 | 
| 2017-03-25 |    0 | 
| 2017-03-26 |    0 | 
| 2017-03-27 |    0 | 
| 2017-03-28 |    0 | 
| 2017-03-29 |    0 | 
+------------+---------------+ 

Anzahl und Kalender Tabellenverweis:

+0

Die Lösung groß aufzufüllen verwendet, ist aber Es berücksichtigt nicht, dass die Tabelle "TBL_Downloads" über Register von verschiedenen Benutzern verfügt. Sobald ich die "WHERE userid = 292" hinzufüge, verschwinden die Zeilen in cero wieder. Oder vielleicht mache ich etwas falsch –

+0

@AlejandroFlores put 'und userid = 292' in der' linken Join' Bedingung anstelle von einer 'wo' - aktualisiert meine Antwort und die Rextester Demo um zu zeigen, was ich meine. – SqlZim

+0

Ich habe den gleichen Satz vorher verwendet. Ich weiß nicht, warum ich nicht darauf gekommen bin. Es hat perfekt funktioniert. Ich bin ein bisschen neu darin, also vielen Dank. –

0

Sie Gruppe verwenden können für diesen Monat durch Zählung zu finden und erzeugen Daten Common Table Expressions

--Final Query - For this query to execute you require #dates to be populated as below 
select cte_start_date as [date], coalesce(cnt,0) as DownLoadCount from #dates d left join 
(
    select userid,convert(date,DownloadDate) dt , count(convert(date,DownloadDate)) as cnt from #yourDownloads 
    group by userid, convert(date,DownloadDate) 
) a 
on d.cte_start_date = a.dt 

Common Table Expression rekursive Abfrage Datum

--Populuating dates 
declare @start_date date = '02-01-2016' 
declare @end_date date = eomonth('02-01-2016') 
;WITH CTE AS 
(
    SELECT @start_date AS cte_start_date 
    UNION ALL 
    SELECT DATEADD(DAY, 1, cte_start_date) 
    FROM CTE 
    WHERE DATEADD(DAY, 1, cte_start_date) <= @end_date  
) 
select * into #dates from cte 

Ihre Eingabetabelle

create table #yourDownloads (UserId int, ImageId int, DownloadDate datetime) 

insert into #yourDownloads 
(UserID , ImageID , DownloadDate ) values 
( 292 , 782 ,'02-01-2016 14:20:22.737') 
,( 292 , 783 ,'02-01-2016 14:20:22.737') 
,( 292 , 784 ,'02-02-2016 14:20:22.737') 
,( 292 , 785 ,'02-04-2016 14:20:22.737') 
,( 292 , 786 ,'02-05-2016 14:20:22.737') 
,( 292 , 787 ,'02-06-2016 14:20:22.737') 
+0

Sie können die Leistung der rekursiven Cte im Vergleich zu einigen anderen Optionen überprüfen. Es wird ziemlich schlecht, da Sie mehr Werte generieren müssen. [Erstellen Sie einen Satz oder eine Sequenz ohne Schleifen - 2 - Aaron Bertrand] (https://sqlperformance.com/2013/01/t-sql-queries/generate-a-set -2) – SqlZim

Verwandte Themen