2012-02-16 18 views
5

Prawie się denerwuję próbując rozwiązać ten problem:Zapytanie SQL zliczać zarejestrowanych użytkowników dziennie

W mojej aplikacji użytkownicy mogą się rejestrować i usuwać siebie. Data utworzenia i data usunięcia są przechowywane w bazie danych jako znacznik czasu. Muszę wiedzieć, każdego dnia w ciągu kilku dni, ile zarejestrowanych i nie usuniętych użytkowników istniało w tym dniu.

Jeśli mam 10 istniejących użytkowników w dniu 2012-02-01, jednego użytkownika, który usunął konto w dniu 2012-02-03, trzech użytkowników zarejestrowanych w dniu 2012-02-04 i dwóch użytkowników usuniętych w dniu 2012-02- 06 i kwerendy łączną liczbę zarejestrowanych użytkowników od 2012-02-01 aż 2012-02-07 Chciałbym uzyskać wynik takiego:

 
day    total_users 
2012-02-01  10 
2012-02-02  10 
2012-02-03  9 
2012-02-04  12 
2012-02-05  12 
2012-02-06  10 
2012-02-07  10 

to jest jak moja uproszczona tabela użytkownik wygląda następująco:

user_id, nazwa_użytkownika, created_at, deleted_at

to żaden problem, aby uzyskać numer o f zarejestrowany i nie usuniętych użytkowników do jednego konkretnego dnia (tutaj 2012-02-01, który dostanie mi 10 w moim przykładzie):

select application.application_id as application_id, count(user.user_id) as user_total 
from application, user 
where application.application_id = user.application_id 
and date(user.created_at) <= '2012-02-01' 
and ((date(user.deleted_at) > '2012-02-01') or (user.deleted_at is null)) 

Kto ma pojęcia, w jaki sposób można utworzyć kwerendę (bez kursora), który będzie miał mój oczekiwany wynik? Moja baza danych to MySQL 5.0.51 na Debianie.

góry dzięki Marcus

Odpowiedz

2

Jeśli masz tabelę z listą dat w nim (zwany coś takiego jak kalendarz), można użyć kwerendy tak:

select c.calendar_date, count(*) user_total 
from calendar c 
left join user u 
     on date(u.created_at) <= c.calendar_date and 
      (date(u.deleted_at) > c.calendar_date or u.deleted_at is null) 
group by c.calendar_date 

Jeśli nie masz tabeli z listą dat, możesz ją zasymulować za pomocą następującego zapytania:

select * from 
(select adddate('1970-01-01',t4.i*10000 + t3.i*1000 + t2.i*100 + t1.i*10 + t0.i) calendar_date from 
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t0, 
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t1, 
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t2, 
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t3, 
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t4) v 
where calendar_date between ? /*start of date range*/ and ? /*end of date range*/ 
+0

Dziękuję bardzo, to działa idealnie! Musiałem tylko zamienić "i" w każdej linii na t0, t1 itd. Myślę, że to moja stara wina serwera MySQL. –

+0

@MarcusMuench: Ups, moja wina. Poprawiłem zapytanie - dziękuję. –

2
SELECT date(user.created_at) as "creation_date", count(user.user_id) as "user_total" 
FROM application a 
INNER JOIN user u ON a.application_id = u.application_id 
WHERE date(user.created_at) <= '2012-02-01' 
AND ((date(user.deleted_at) > '2012-02-01') or (user.deleted_at is null)) 
GROUP BY date(user.created_at) 
ORDER BY date(user.created_at) ASC 
+0

+1. @ user1214154, pamiętaj, że nie będzie to lista dat, które nie mają żadnych zarejestrowanych użytkowników w tym dniu z 0 jako liczba. będzie wyświetlał tylko dni, które istnieją w tabeli – talereader

+0

Nie zwróci to liczby zarejestrowanych użytkowników dla każdego dnia - zamiast tego zwróci liczbę użytkowników, którzy zarejestrowali się * na * każdego dnia. Biorąc pod uwagę przykładowe dane opisane w pytaniu, nie wytworzy on wymaganej wydajności - zamiast tego stworzy liczbę użytkowników i dat sprzed 2012-02-01 (łącznie do 10 użytkowników), a po 2012 - 02-01. –