Farklı invervals ile gruplama ihtiyaç sorgularda yükünü en aza indirmek için nasıl?

2 Cevap php

Ben nasıl sorguları hızlandırmak için iyi bir uygulama tavsiye ve tarih / mktime işlevleri çağırmak için gereken yükü en aza indirmek için aynı zamanda bakıyorum. Ben aşağıdaki tabloda düzeni ile uğraşıyorum sorunu önemsizleştirmenin:

CREATE TABLE my_table(
  id INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT,   
  important_data INTEGER,
  date INTEGER);

Kullanıcı iki tarih arasında 1) tüm kayıtları göstermek için seçebilirsiniz:

SELECT * FROM my_table 
  WHERE date >= ? AND date <= ? 
  ORDER BY date DESC;

Çıktı:

10-21-2009 12:12:12, 10002
10-21-2009 14:12:12, 15002
10-22-2009 14:05:01, 20030
10-23-2009 15:23:35, 300
....

Ben bu durumda geliştirmek için pek bir şey olduğunu sanmıyorum.

Gün 2) özetler / grup çıktı, hafta, ay, yıl:

SELECT COUNT(*) AS count, SUM(important_data) AS important_data
  FROM my_table 
  WHERE date >= ? AND date <= ? 
  ORDER BY date DESC;

Aylara göre örnek çıktı:

10-2009, 100002
11-2009, 200030
12-2009, 3000
01-2010, 0 /* <- very important to show empty dates, with no entries in the table! */
....

2) Şu anda için döngü aşağıdaki gibi bir mktime / tarih ile çok pahalı koşuyorum seçeneği gerçekleştirmek için:

for(...){ /* example for group by day */
  $span_from = (int)mktime(0, 0, 0, date("m", $time_min), date("d", $time_min)+$i, date("Y", $time_min));
  $span_to = (int)mktime(0, 0, 0, date("m", $time_min), date("d", $time_min)+$i+1, date("Y", $time_min)); 
  $query = "..";  
  $output = date("m-d-y", ..);
}

Benim fikirlerim kadar nelerdir? Gün (20091212) için ek / gereksiz sütunları (INTEGER) Ekle, ay (200.912), hafta (200.942) ve yıl (2009). Bu şekilde ben döngü için tüm gereksiz sorguları kurtulabilirsiniz. Ancak ben hala çok hızla veritabanında herhangi bir eşdeğeri yok tüm tarihleri ​​hesaplamak için sorunla karşı karşıya ediyorum. Sadece sorunu taşımak için bir yolu MySQL işi yapalım ve sadece sol join (data) ile (MySQL tarih fonksiyonları kullanmak / tüm tarihlerini hesaplamak) büyük bir sorgu kullanmak olabilir. Bu MySQL ekstra yük atalım akıllıca olurdu? Neyse ben döngü için tüm bu mktime / tarih kullanmak için isteksiz. Ben masa düzeni ve kod üzerinde tam kontrole sahip olduğundan bile büyük değişiklikler önerilerinizi bekliyoruz!

Update

Greg sayesinde ben aşağıdaki SQL sorgusu ile geldi. Ancak yine de hata bana sql tabloların 50 satır kullanmak - php ile kurmak - belki daha hızlı ve daha zarif aksi yapılabilir ki:

SELECT * FROM (  
  SELECT DATE_ADD('2009-01-30', INTERVAL 0 DAY) AS day UNION ALL
  SELECT DATE_ADD('2009-01-30', INTERVAL 1 DAY) AS day UNION ALL
  SELECT DATE_ADD('2009-01-30', INTERVAL 2 DAY) AS day UNION ALL
  SELECT DATE_ADD('2009-01-30', INTERVAL 3 DAY) AS day UNION ALL
  ......
  SELECT DATE_ADD('2009-01-30', INTERVAL 50 DAY) AS day ) AS dates
LEFT JOIN (
    SELECT DATE_FORMAT(date, '%Y-%m-%d') AS date, SUM(data) AS data
    FROM test 
    GROUP BY date  
  ) AS results
ON DATE_FORMAT(dates.day, '%Y-%m-%d') = results.date;

2 Cevap

You definitely shouldn't be doing a query inside a loop. You can group like this:

SELECT COUNT(*) AS count, SUM(important_data) AS important_data, DATE_FORMAT('%Y-%m', date) AS month
  FROM my_table 
  WHERE date BETWEEN ? AND ? -- This should be the min and max of the whole range
  GROUP BY  DATE_FORMAT('%Y-%m', date)
  ORDER BY date DESC;

Sonra (bu döngü CPU üzerinde oldukça hafif olmalıdır) yapıyorsun gibi veri aralığında tarih ve döngü anahtarlı bir diziye bu çekin.

Başka bir fikir sorgu içinde dize kullanmak değildir. Mysql üzerinde, datetime dize parametresi Transform.

STR_TO_DATE(str,format)

http://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html