Fusion Tables: Count Distinct mit Sum Workaround

SQL (Basis)

person   day       breakfast
Bob      Monday    Toast
Bob      Tuesday   Cereal
Kat      Monday    Toast
Kat      Tuesday   Toast
Steve    Monday    Cereal

SELECT 
  person,
  COUNT(*),
  COUNT(DISTINCT breakfast) 
FROM 1234

person  COUNT(*)   COUNT(DISTINCT breakfast)
Bob     2          2
Kat     2          1
Steve   1          1

SQL (Fusion)

person   day       breakfast  count_rows  distinct_breakfast_by_person
Bob      Monday    Toast      1           1
Bob      Tuesday   Cereal     1           1
Kat      Monday    Toast      1           1
Kat      Tuesday   Toast      1           1
Kat                           0          -1
Steve    Monday    Cereal     1           1

SELECT 
  person,
  SUM(count_rows) as count_rows, 
  SUM(distinct_breakfast_by_person) as count_distinct_breakfast
FROM 1WiwP-psSP9LDOKbBnbTS_KayYHuArXRJn39av1I
GROUP BY person

person  COUNT(*)   SUM(distinct_breakfast_by_person)
Bob     2          2
Kat     2          1
Steve   1          1

Fusion Table: group by month(date)

Workaround: group by month (SQL Command-Client)

1. Detect range

SELECT
  MINIMUM(DATE),
  MAXIMUM(DATE)
FROM 1_-4yMRfmTEVnvV9EKryq-faNoXDaJ1KIq4ACM18
LIMIT 2

2. Loop Month/Year

SELECT
  USERID,
  SUM(HITS),
  COUNT()
FROM 1_-4yMRfmTEVnvV9EKryq-faNoXDaJ1KIq4ACM18
WHERE
  DATE = 'JAN/2010'
GROUP BY
  USERID
LIMIT 5

... UNION ALL by Client JavaScript ...

SELECT
  USERID,
  SUM(HITS),
  COUNT()
FROM 1_-4yMRfmTEVnvV9EKryq-faNoXDaJ1KIq4ACM18
WHERE
  DATE = 'FEB/2010'
GROUP BY
  USERID
LIMIT 5

3. Loop Week/Year

SELECT
  USERID,
  SUM(HITS),
  COUNT()
FROM 1_-4yMRfmTEVnvV9EKryq-faNoXDaJ1KIq4ACM18
WHERE
  DATE >= 'JAN 01, 2010' AND DATE <= 'JAN 07, 2010'
GROUP BY
  USERID
LIMIT 5

... or count(*) by week ...

SELECT
  DATE,
  COUNT()
FROM 1_-4yMRfmTEVnvV9EKryq-faNoXDaJ1KIq4ACM18
WHERE
  DATE >= 'JAN 01, 2010' AND DATE <= 'JAN 07, 2010'
GROUP BY
  DATE
LIMIT 10

JavaScript – Database API

KeyValue – localStorage (IE 8, Firefox 3.5, Safari 4)
http://simplehomepage.appspot.com/sql/local-storage.htm

SQLite – openDatabase (Safari, Firefox 3.51, Chrome)
http://simplehomepage.appspot.com/sql/open-database.htm

SQLite – Kripken SQL.js (compiled through Emscripten)
http://simplehomepage.appspot.com/sql/kripken-sql.htm

Automatisch Texte mit Google Translate übersetzen

Mit Google Translate können Texte auf einer Homepage automatisch übersetzt werden. Damit können mehrsprachige Formulare, Menüs und ansatzweise auch Inhalte auf Knopfdruck generiert werden.

Mit einer Webseite in mehreren Sprachen kann man deutlich mehr Benutzer erreichen. Die Übersetzung ist zwar nicht perfekt, aber bei einfachen Sätzen und einfacher Grammatik funktioniert es bereits recht gut.
Mehr von diesem Beitrag lesen

Batch per Cron, Tasks und Backends mit Google App Engine realisieren

Mit der Google App Engine ist es sehr einfach möglich langlaufende Programme per Batch im Hintergrund asynchron zu starten. Kleine Tasks mit einer Laufzeit von bis zu 10 Minuten können über den Webserver ausgeführt werden. Für echte Batches, die mehreren Stunden dauern, können mehrere separate Backend Server genutzt werden.

Das Limit liegt derzeit bei 48 GHz für die CPU und 10 GB für den RAM. Die kleinste Serverinstanz mit 600 MHz und 128 MB kosten ab 0,08 US-Dollar pro Stunde. Insgesamt können bis zu fünf verschiedene Backends definiert werden.

Google Appengine Backends

GAE Admin Console Backends

Mehr von diesem Beitrag lesen

GV100 Parser für Python

Mit dem nachfolgenden Quellcode kann die Datenbank GV100 vom Statistischen Bundesamt mit Python eingelesen und z.B. in einer Google App Engine zur Gliederung von Adressen nach Gemeinde, Kreis, Bezirk und Bundesland genutzt werden. Das Gemeindeverzeichnis wird quartalsweise aktualisiert und steht jedem kostenlos als Download (Mrz, Jun, Sep, Dez) zur Verfügung.

Die Datei GV100.asc enthält alle 12.000 Orte aus Deutschland inklusive Postleitzahl und wird von zahlreichen Internetseiten als PLZ-Suche aufgearbeitet. Die Daten werden auch als SEO-Werkzeug zur Suchmaschinenoptimierung eingesetzt, um alle Ortsnamen mit beliebigen Keywords zu verknüpfen. Mit der Kombination von Suchbegriffen – „Autohaus Hintertupfingen“ oder „Hotel Hintertupfingen“ – können so sehr viele Internetseiten generiert werden.
Mehr von diesem Beitrag lesen

Virtual Hosts WebApp für Google App Engine ermöglicht Domain Masking / Multiple Hostname

Mit einem kleinen Workaround ist es möglich mehrere Domains über eine einzelne Google App Engine zu betreiben. Am einfachsten lassen sich multiple Hostnames bzw. Domain Masking für eine WebApp realisieren. Es funktioniert ähnlich Name-based Virtual Hosts bei einem Apache Webserver.

Virtual Hosts WebApp für Google App Engine

Für mein SimpleHomePage Framework wollte ich ähnlich Confixx mehrere Domains über eine App Engine betreiben und das Domain Masking über ein Admin Frontend dynamisch konfigurieren. Der Trick ist, dass ich abhängig vom HOST_NAME in os.environ das URL-Mapping in der Main-Methode steuere. Damit lassen sich beliebig viele Domains über eine Instanz betreiben. Mehr von diesem Beitrag lesen

Google App Engine – Datastore Container – Performance Serialisierung mit pickle versus marshal

Da die Google App Engine pro Tag nur 50k Operationen auf den Datastore spendiert, kann man als Workaround einen Container mit mehreren Datensätzen im Datastore abspeichern. Ist z.B. ein Datensatz 500 Byte groß, dann können in einem Datastore-Container bis zu 2.000 Datensätze gespeichert werden.

Als Container eignet sich eine Hash-Liste, die als Key die ID oder den NAME des Datensatzes enthält. Die Liste wird dann serialisiert in einem BlobProperty gespeichert und der Spacebedarf kann zusätzlich mittels ZIP-Kompression reduziert werden.

Frage: Was ist schneller Marshal oder Pickle?
Antwort: Marshal ist 10 mal schneller als Pickle. 

Beim der Realisierung des Datastore-Container musste ich unbedingt die Vorgaben von Google beachten, dass ein Skript nicht langsamer als eine Sekunden sein darf. App Engines, bei denen Skripte länger als 1.000 ms laufen werden von Google in eine spezielle Sandbox ausgesondert.

Meine Implementierung vom Datastore-Container basiert auf Python. In dieser Sprache gibt es mehrere Möglichkeiten der Serialisierung und Deserialisierung eines Objektes, um dieses in einer Datei oder als Blob in der Datenbank zu speichern. Zunächst habe ich auf Pickle gesetzt, aber die Performance war in Python 2.5.4 sehr schlecht – 250 ms je Operation (Get, Put, Delete) bei einer Hash-Liste mit 300 Zeilen und 100 KB Space.

Mehr von diesem Beitrag lesen

1-zu-N Beziehung für Google AppEngine

Relation Land (1:N) Bundesland mit Google AppEngine abbilden.

Beispiel:

print "db.Model"

from google.appengine.ext import db

class tbl_land(db.Model):
id_land = db.StringProperty(required=True)
land = db.StringProperty()

class tbl_bundesland(db.Model):
ref_land = db.ReferenceProperty(tbl_land,collection_name=’ref_bundesland‘)
id_bundesland = db.StringProperty(required=True)
bundesland = db.StringProperty()

Mehr von diesem Beitrag lesen

Domain Check mit GAE urlfetch

Kleiner Workaround für die Google App Engine, um die Existenz einer Domain zu überprüfen. Statt der Library socket wird urlfetch aus der google.appengine.api verwendet.

Mehr von diesem Beitrag lesen