2009-05-03 11 views
0

Ich verwende SQLite in einer Anwendung, die ich entwickle.
Ich versuche, eine ziemlich komplexe Abfrage (komplex für mich!) Auszuführen und ich habe die grundlegenden Ergebnisse, die ich brauche, aber ich bin fest auf über die letzte Hürde zu bekommen.Verwenden mehrerer Tabellen, mehrere Werte mit Min() SQL

Ich habe diese Abfrage derzeit das tut, was ich brauche, es zu tun ...

SELECT SUM(activity) 
FROM activities 
WHERE activity_id IN(SELECT name_id FROM foods GROUP BY name_id HAVING SUM(points) > 20); 

Ich brauche einen anderen Teil auf diese Abfrage hinzuzufügen, aber das ist, wo es ein wenig kompliziert für mich bekommen hat. Es gibt drei Tabellen .... Daten, Lebensmittel, Aktivitäten und ich muss die Summe einer Ergebnismenge finden, die die minimale Zahl zwischen zwei Werten aus zwei verschiedenen Tabellen enthält, solange eine bestimmte Aussage wahr ist.

Grundsätzlich ..

SELECT SUM(total) FROM (SELECT MIN(value from table1 which is determined by a value in table2, value from table3) AS total 
FROM table3 
WHERE value from table3 is contained in a result set from table1); 

Die folgende Abfrage ist etwas, was ich mit, dass kam funktionieren würde, wenn es keine Syntax überhaupt war (lol!). Das funktioniert nicht, aber ich wollte es nur zeigen, um besser zu verstehen, was ich zu tun versuche.

SELECT SUM(activity_amount) FROM (SELECT min((SELECT SUM(points) - 20 FROM foods WHERE name_id IN(SELECT pk FROM dates WHERE weekly=1) GROUP BY name_id), activity) AS activity_amount 
FROM activities 
WHERE activity_id IN(SELECT name_id FROM foods GROUP BY name_id HAVING SUM(points) > 20)); 

Das Problem ist, mit dem ersten Wert in der MIN() ....

SELECT SUM(points) - 20 FROM food WHERE name_id IN(SELECT pk FROM dates WHERE weekly=1) GROUP BY name_id 

Diese Aussage mehr als ein Wert ergibt, aber auch wenn ich diese Werte tun müssen gegen andere in der MIN() vergleichen Ich brauche sie nur einzeln, nicht als Ganzes.

Wie kann ich etwas wie die obige Abfrage erhalten, die ich erstellt habe, um zu arbeiten?

EDIT ... einige Beispieltabellen, um besser zu helfen. Dank jellomonkey und hainstech

Table#1(dates) 

CREATE TABLE dates (pk INTEGER PRIMARY KEY, date INTEGER, weekly INTEGER) 
pk date  weekly 
1 05062009 1 
2 05072009 1 
3 05082009 2 

Table #2(foods) 

CREATE TABLE foods (pk INTEGER PRIMARY KEY, food VARCHAR(64), points DOUBLE, name_id INTEGER) 
pk food points name_id 
1 food1 12.0  1 
2 food2 9.0  1 
3 food3 5.0  1 
4 food4 15.0  2 
5 food5 14.0  2 
6 food6 12.0  3 

Table#3(activities) 

CREATE TABLE activities (pk INTEGER PRIMARY KEY, activity DOUBLE, activity_id INTEGER) 
pk activity activity_id 
1  5.0   1 
2  4.0   1 
3  2.0   2 
4  4.0   3 

Mit dieser ex und Abfrage von meiner ursprünglichen Post (eine, die nicht funktioniert), würde ich für eine Ergebnismenge suchen, die einen value..8.0

MIN (26,0 -20, 9,0) = 6,0
MIN (29,0-20, 2,0) = 2,0
6,0 + 2,0 = 8,0

ich hoffe, das hilft!

+0

könnten Sie geben! ein kleines Tischbeispiel (so einfach wie möglich) und ein wenig gewünschtes Ergebnisset? – jellomonkey

+0

ok. Ich habe meinen Beitrag bearbeitet, um ein Beispiel hinzuzufügen. Vielen Dank!! – freddyD

Antwort

2

Nach viel Kopf-Kratzen und Wünschelrute Ich vermute, was Sie wollen, könnte sein, :

SELECT SUM(MIN(fp-20, ap)) FROM 
    (SELECT dates.pk AS fd, SUM(points) AS fp 
    FROM dates 
    JOIN foods ON name_id = fd 
    GROUP BY fd 
    HAVING fp >= 20) 
    JOIN 
    (SELECT dates.pk AS ad, SUM(activity) AS ap 
    FROM dates 
    JOIN activities ON activity_id = ad 
    GROUP BY ad) 
    ON fd = ad 

Die Spaltennamen Null Verbindung zu ihrer Bedeutung zu haben scheinen, aber, hey, zumindest dieser 8.0 nicht geben und die Subselects die anderen Zahlen geben Sie erwähnen -)

+0

Alex, vielen Dank !! Das hat super funktioniert. Die einzige andere Sache, die ich von Ihnen fragen würde, ist, dass diese Abfrage alle PKs von Daten berücksichtigt. Wie würde ich nur die pk von Daten abrufen, wo "weekly = 1" ?? Ich denke, wo Sie haben "... FROM Daten JOIN Lebensmittel ON Name_ID ....", kann ich das ".... FROM Datumsangaben WO wöchentlich = 1 JOIN Lebensmittel ON Name_ID ....". Wird es funktionieren? – freddyD

+0

Alex, ich denke darüber nach und ich denke nicht, dass das funktionieren wird, was ich vorgeschlagen habe, oder? Ich denke, dass das mit JOIN einen Fehler verursachen wird? – freddyD

+0

syntaktisch, 'WHERE dates.weekly = 1' geht _after_ der JOIN und Sie brauchen es in beiden inneren SELECTs. –

1

Vereinbaren Sie mit Jellomonkey - Ich kann nicht genau verstehen, was Sie wollen, es sei denn, Sie zeigen mehr Informationen. Einfache Tabellendefinitionen, einige Zeilen mit Beispieldaten und die erwartete Ausgabe würden helfen.

Hier ist ein einfaches Beispiel für einen Minimalwert von einem Tisch zu bekommen, basierend auf einem Bereich, deren Grenzen in zwei anderen Tabellen definiert sind:

create table t1(t1id int primary key, value int) 
create table t2(t1id int, t2id int primary key, value int) 
create table t3(t2id int, t3id int primary key, value int) 

select 
    MIN(t1.value) 
from table1 as t1 
    join table2 as t2 on t2.t1id = t1.t1id 
    join table3 as t3 on t3.t2id = t2.t2id 
where t1.value between t2.value and t3.value 

Dies verwendet t2.value und t3.value als die Grenzen der Bereich zum Finden der MIN() in.

EDIT - danke für die Buchung der Beispieltabellen, die eine Tonne hilft. Sie könnten einige zusammengefasste CASE-Anweisungen verwenden, um die beiden Werte zu vergleichen, aber ich würde damit beginnen, sie in ein Rowset zu bringen und eine normale MIN-Aggregation durchzuführen. Dies wird besser lesbar sein und Ihnen auch die Möglichkeit geben, weitere Informationen hinzuzufügen, die Sie bei Bedarf in Ihre MIN-Eingänge aufnehmen können.Also hier ist ein kurzer Schlag auf das, was ich tun würde:

select 
    SUM(activity) 
from (
    select 
     min(activity) as activity 
     ,activity_id 
    from (
     select 
      SUM(activity) as activity, activity_id 
     from activities 
     group by activity_id 
     union all 
     select 
      SUM(points)-20 
      ,name_id 
     from foods 
     group by name_id 
     having SUM(points) > 20 
    ) as activitySum 
    where activity_id in (select pk from dates where weekly=1) 
    group by activity_id 
) as activityLesserOf 

Edit # 2 - hinzugefügt, DIE oben Abfrage pro Klärung Bedürfnisse

+0

hey thanks ... Ich war schon in der Mitte, wenn ich die Beispieltabellen hinzufüge, als ich deinen Post sah, also habe ich es gerade beendet. Ich werde versuchen, Ihren Vorschlag umzusetzen. Wie auch immer, ich bearbeitet mein OP, um ein Beispiel zu enthalten – freddyD

+0

dies funktionierte, wie die Abfrage entworfen ist, aber eigentlich brauchte ich etwas ein wenig anders, und ich denke, das ist meine Schuld für die Erklärung nicht besser. In meiner Anwendung, wo ich dies implementieren werde, interessiert mich nur die name_id, wo die Punkte größer als 20 ist. Die Summe (Punkte) und subtrahieren 20 würde nur getan werden, wo Punkte größer als 20 ist. Ich schätze es wirklich, weil dies sah gut aus und ich wünschte, ich wäre gut genug mit SQL zu wissen, wo ein Teil hinzufügen, um dies geschehen zu lassen ... irgendwelche Gedanken? – freddyD

+0

@freddyD - Wenn ich richtig verstehe, möchten Sie alle Aggregationen aus der Tabelle Lebensmittel herausfiltern, wo die Summe() weniger als 20 ist, oder? Sie filtern Post-Aggregation-Werte mit HAVING. Es ist im Grunde dasselbe wie WHERE, außer dass WHERE vor der Aggregation angewendet wird und HAVING danach angewendet wird. Ich habe es der obigen Abfrage hinzugefügt, lassen Sie uns wissen, ob dies das ist, was Sie suchen. – ahains

Verwandte Themen