2016-10-29 3 views
1

Zuerst einige Hintergrundinformationen zu meinem Problem:
Ich baue einen Crawler und möchte einige Highscore-Listen überwachen.
Die Highscore-Listen sind durch zwei Parameter definiert: eine Kategorie und eine Sammlung (zusammen einzigartig).
Nach einem erfolgreichen Download erstelle ich einen neuen Statistikeintrag (category, collection, createdAt, ...)Sqlite relative Komplement auf kombinierten Schlüssel

Problem: Ich möchte die Highscoreliste nur einmal pro Tag abfragen. Also brauche ich eine Abfrage, die Kategorie und Sammlung zurückgibt, die nicht in 24h heruntergeladen wurden. Die Statistik Tabelle sollte dafür verwendet werden.
Ich habe eine Liste aller möglichen Kategorien und aller möglichen Sammlungen. Sie arbeiten wie ein Cross-Join. Also im Grunde brauche ich das relative Komplement des Kreuzes mit den Einträgen der letzten 24h

Meine Idee: Cross Join Kategorien und Sammlungen und "Subtrahieren" alle Paare (Kategorie, Sammlung) von Statistiken Einträge, die während erstellt wurde Letzte 24 h

Frage 1: Ist es möglich, Kategorien und Sammlungen in der Abfrage zu definieren und sie zu verbinden oder muss ich eine Tabelle für sie erstellen?

Frage 2: Ist meine Idee der richtige Ansatz? Wie würdest du das in Sqlite machen?

Ok ich erkenne, dass dies vielleicht verwirrend klingt, so zeichnete ich ein Bild von dem, was ich eigentlich will. enter image description here

Ich bin an C.

Hier ist mein aktueller Code in Java, vielleicht hilft es, das Problem zu verstehen:

public List<Pair<String, String>> getCollectionsToDownload() throws SQLException { 
    long threshold = System.currentTimeMillis() - DAY; 
    QueryBuilder<TopAppStatistics, Long> query = queryBuilder(); 
    List<TopAppStatistics> collectionsNotToQuery = query.where().ge(TopAppStatistics.CREATED_AT, threshold).query(); 

    List<Pair<String, String>> toDownload = crossJoin(); 
    for (TopAppStatistics stat : collectionsNotToQuery) { 
    toDownload.remove(new Pair<>(stat.getCategory(), stat.getCollection())); 
    } 
    return toDownload; 
} 

private List<Pair<String, String>> crossJoin() { 
    String[] categories = PlayUrls.CATEGORIES; 
    String[] collections = PlayUrls.COLLECTIONS; 
    List<Pair<String, String>> toDownload = new ArrayList<>(); 
    for (String ca : categories) { 
    for (String co : collections) { 
     toDownload.add(new Pair<>(ca, co)); 
    } 
    } 
    return toDownload; 
} 

Antwort

1

Die einfachste Lösung für Ihr Problem ist ein AUSSER. Angenommen, Sie haben eine Unterabfrage , die A berechnet und eine andere, die B berechnet. Diese Abfragen können sehr komplex sein. Der Schlüssel ist, dass beide die gleiche Anzahl von Spalten und vergleichbaren Datentypen zurückgeben sollten.

In SQLite können Sie dann tun:

<your subquery 1> EXCEPT <your subquery 2> 

So einfach ist das.

Zum Beispiel:

SELECT a, b FROM T where a > 10 
EXCEPT 
SELECT a,b FROM T where b < 5; 

Denken Sie daran, beiden Unterabfragen müssen die gleiche Anzahl von Spalten zurück.