SQL Problem mit ALL

Hallo,

also ich muss hier folgende Aufgabe lösen:

Bestimme die Kundennummern der Kunden, die bereits alle Produkte bestellt haben.

Hier ist die dazugehörige CAP-Datenbank
http://img201.imageshack.us/img201/2520/81524148tp0.jpg
http://img147.imageshack.us/img147/664/84831977cr4.jpg

Hab die Aufgabe jetzt versucht mit folgenden SQL Anweisung zu lösen:

SELECT cid FROM orders WHERE pid =ALL (SELECT pid from products)

Also mit dem Subquery wähle ich alle produkte aus die es gibt(Hab also die Menge von Produkte…)
Und dann vergleich ich halt die einzelnen Elemente aus der Relation “orders” mit =ALL…

Jetzt müsste der doch jedes Element mit der Menge vergleichen und dann die jeweilige cid ausgeben…aber macht der nicht… :frowning:

vllt. bin ich ja auch völlig auf den falschen weg aber komm da jetzt gar net mehr weiter und bin schon am verzweifeln -_-

Vllt. weiss ja jemand von euch rat, wäre sehr dankbar!!

greetz

  1. Bist Du Dir sicher, mit PostgreSQL zu arbeiten?
  2. ich mag keine Bilder, wenn man es nicht auch klar und einfach mit passenden DDL und DML-Befehlen darstellen kann, was für Tabellen und Daten man hat.

Du würdest es potentiellen Helfern erheblich vereinfachen, Deine Tabellen mit CREATE TABLE und INSERT INTO … hier zu erklären.

Andreas

wie mit create table erklären? weiss jetzt gerade nicht was du meinst
postgreSQL?!? gibts da unterschiede hab da jetzt gar net so darauf geachtet -_-
fals es nicht das selbe is dann bin ich hier glaub ich sowieso falsch :stuck_out_tongue:

hab jetzt nur SQL gelesen^^



test=# create table produkte (pid serial primary key, name text);
NOTICE:  CREATE TABLE will create implicit sequence "produkte_pid_seq" for serial column "produkte.pid"
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "produkte_pkey" for table "produkte"
CREATE TABLE
Time: 22,619 ms
test=*# copy produkte(name) from stdin;
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself.
>> prod1
>> prod2
>> prod3
>> \.
Time: 7301,329 ms

Sowas halt.

postgreSQL?!? gibts da unterschiede hab da jetzt gar net so darauf geachtet -_-
fals es nicht das selbe is dann bin ich hier glaub ich sowieso falsch :stuck_out_tongue:

hab jetzt nur SQL gelesen^^

Unterschiede gibt es da sehr wohl, aber auch einen gemeinsammen Nenner. Möglicherweise wird Dir hier jemand eine Lösung zeigen, die für Dich nicht funktioniert.

Ich hab grad keine Zeit.

Andreas

Nun doch.

test=# select * from kunden;
 kid |  name
-----+--------
   1 | kunde1
   2 | kunde2
(2 rows)

Time: 0,176 ms
test=*# select * from produkte;
 pid | name
-----+-------
   1 | prod1
   2 | prod2
   3 | prod3
(3 rows)

Time: 0,336 ms
test=*# select * from umsatz;
 id | pid | kid
----+-----+-----
  4 |   1 |   1
  5 |   1 |   2
  6 |   2 |   1
  7 |   3 |   1
(4 rows)

Dabei ist Tabelle umsatz so definiert:

test=*# \d umsatz
                         Table "public.umsatz"
 Column |  Type   |                      Modifiers
--------+---------+-----------------------------------------------------
 id     | integer | not null default nextval('umsatz_id_seq'::regclass)
 pid    | integer |
 kid    | integer |
Indexes:
    "umsatz_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
    "umsatz_kid_fkey" FOREIGN KEY (kid) REFERENCES kunden(kid)
    "umsatz_pid_fkey" FOREIGN KEY (pid) REFERENCES produkte(pid)

Nun bastle ich mir eine Aggregatfunktion. Faul wie ich bin kopiere ich die direkt aus der Doku PostgreSQL: Documentation: Manuals: PostgreSQL 8.3: User-Defined Aggregates :

CREATE AGGREGATE array_accum (anyelement)
(
    sfunc = array_append,
    stype = anyarray,
    initcond = '{}'
);

Nun geht folgendes SQL ganz leicht von der Hand:

test=*# select kid, array_accum(pid) as produkte from umsatz group by 1 having array_accum(pid)=ARRAY(SELECT pid FROM produkte);
 kid | produkte
-----+----------
   1 | {1,2,3}
(1 row)

Wir wir sehen, erfüllt Kunde mit kid=1 die Bedingung, alle Produkte gekauft zu haben.

Andreas

Nachtrag: man muß aufpassen bei dieser Lösung, wenn Kunden einen Artikel mehrfach gekauft haben, und auch das die id-werte in den Arrays jeweils sortiert sind, damit diese verglichen werden können. Aber das ist auch nur eine kleine Änderung am SQL…

test=*# select kid, array_accum(pid) as produkte from (SELECT DISTINCT umsatz.pid, umsatz.kid FROM umsatz ORDER BY umsatz.pid, umsatz.kid) umsatz_distinct group by 1 having array_accum(pid)=ARRAY(SELECT pid FROM produkte order by pid);

Wer nun noch Fehler findet, bekommt ein Bienchen.

Andreas