relationale algebra
Post on 15-Apr-2017
1.200 Views
Preview:
TRANSCRIPT
Was bedeutet eigentlich 'RelationaleAlgebra'?
Die wunderbare Welt von Isotopp
Mittwoch, 28. April 2010Was bedeutet eigentlich 'Relationale Algebra'?SQL ist eine Abfragesprache, die als mathematischen Unterbau die
Relationenalgebra hat. Was genau ist das?
Da ist einmal der Begriff der "Algebra". In der Wikipedia findet man
die mathematische Definition der algebraischen Struktur, und sieist, weil sie mathematischen Formalismen genügen muß, für den
ungeübten ein wenig unhandlich zu lesen.
Dort steht aber nix anderes als 'Wir haben eine Grundmenge A und
einen definierten Satz von erlaubten Operationen auf A, und wir
garantieren, das das Ergebnis jeder Operation wieder in A liegt.' Mehr
nicht. Eine Algebra ist also eine Struktur, die Elemente enthält, mit
denen man rechnen kann (etwa die natürlichen Zahlen), und
Operationen, die definieren, was erlaubte Rechenoperationen sind (etwa die Addition). Wenn
etwas eine Algebra ist, dann heißt das, daß man mit dem Ergebnis der Operation wieder in A
landet, also mit dem Ergebnis weiter rechnen kann.
Die natürlichen Zahlen und die Addition sind eine Algebra.
Die natürlichen Zahlen und die Operationen Addition und Subtraktion sind keine Algebra, da 4
minus 6 (4 und 6 sind natürliche Zahlen) den Wert 2 ergibt und 2 ist keine natürliche Zahl wir
haben die Grundmenge verlassen.
In dem Wunsch, mit immer mehr mathematischen Operationen (Addition, Subtraktion,
Multiplikation, Division, Potenzen, Wurzeln, ...) eine Algebra zu bekommen, hat die Mathematik
sich von den natürlichen über die ganzen, die rationalen und schließlich die reellen Zahlen bis zu
den komplexen Zahlen vorgearbeitet.
Dann ist da dieses andere Wort: Was genau ist eine Relation?
Wir kennen den mathematischen Begriff der Funktion.
Eine Funktion bildet eine oder mehrere Mengen zur Gänze oder zum Teil auf eine
Ergebnismenge ab.
Die Funktionsvorschrift sagt, wie das geht.
Die Ergebnisse kann man aufmalen, und dann bekommt man den Graphen der Funktion.
Und um uns zu verwirren, verwenden die Mathefuzzis Funktion, Funktionsvorschrift und den
Graphen der Funktion umgangssprachlich gerne mal synonym.
Die Mathematiker zum Beispiel malen Geraden als Funktion von den reellen Zahlen in die
reellen Zahlen, verwenden die allgemeine Funktionsvorschrift "y = mx + n" (die
Geradengleichung) um die Gerade zu definieren und der Graph der Funktion sieht dann soaus:
Graph der Funktion y=0.5x+2. Jedem xWert ist genau ein yWert zugeordnet.
Eine Funktion liefert für einen Eingangswert genau ein Ergebnis. Für den Wert x=0 bekommenwir aus der oben aufgezeichneten Beispielfunktion den einen Wert y=2 heraus und so weiter.
Eine Relation liefert statt einzelner Werte Teilmengen der Ergebnismenge. Zeichnete man stattder Funktion y = 0.5*x + 2 die Relation y > 0.5*x + 2, dann würde man statt einer Geraden wieoben im Beispiel die Fläche über der Geraden bekommen: Die Relation 'größer als' liefert uns indiesem Zusammenhang nicht einen einzelnen Wert, sondern alle Werte, die für den gegebenenxWert größer als 0.5*x + 2 sind.
Graph der Relation y>0.5x+2. Einem xWert ist eine Menge von yWerten zugeordnet. DieseMenge von yWerten ist eine Teilmenge der Grundmenge.
Das ist genug Mathematik. Wir wollen Informatik machen.
Das bedeutet als erstes einmal: Weg mit den doofen Unendlichkeiten. Komplexe, reelle,rationale, ja sogar natürliche Zahlen das ist alles unendliches, nicht anfaßbares Gekasper vonirgendwelchen Mathespinnern. Wir wollen Werte, die man anfassen und mit dem Debugger imSpeicher sehen kann. Informatik macht Diskrete Mathematik, alles schön endlich. Da kann maneine Funktion dann auch schon mal als Wertetabelle statt als Rechenvorschrift definieren.
Und so landen wir bei den Tabellen.
Grundmenge der Relationenalgebra: Tabellen
Tabellen bestehen aus Zeilen. Eine Zeile kann eine bestimmte Menge von Werten enthalten,
aber bei einer Tabelle enthält jede Zeile gleich viele Werte. In der Mathematik nennt man einKonstrukt mit n Werten ein "nTupel" und schreibt es mit runden Klammern, also (3, 4, 5) für das3Tupel mit den Werten 3, 4 und 5.
In der Informatik gibt es zwei Lager von Leuten. Die einen wollen die Grundmengen von Dingenimmer überall vorher festgelegt haben, also statische Typen. Die anderen wollen an jedem Wertdranstehen haben, aus welcher Grundmenge er stammt, also dynamische Typen. Die meistenSQLDatenbanken wollen statische Typen, verlangen also nicht nur, daß eine Tabelle als "Hat 3Spalten" definiert wird, sondern daß für jede Spalte auch ein Typ festlegt wird: (int, char(20),double) wäre eine solche Festlegung. Von allen SQLDatenbanken, die ich kenne, ist nur Sqlitedynamisch getypt.
Eine Algebra, wir erinnern uns, ist eine Grundmenge und ein Haufen Operationen, und mit denErgebnissen der Operationen wollen wir weiter rechnen können sie müssen also wieder in derGrundmenge liegen.
5 Operationen der Relationenalgebra: Selektion, Projektion, Kreuzprodukt, Umbenennung
und Aggregation
Die Elemente unserer Algebra sollen Tabellen sein, also Mengen von Tupeln: (1, 2, 3), (3, 4, 5),("keks", "cookie", "kex") zum Beispiel. Auf dieser Menge definieren wir nun einen HaufenOperationen. Fünf, um genau zu sein.
root@localhost [kris]> create table a (
-> aid integer unsigned not null
->) engine = innodb;
Query OK, 0 rows affected (0.16 sec)
root@localhost [kris]> insert into a (aid) values (1), (2), (3);
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0
root@localhost [kris]> create table b (
-> bid integer unsigned not null
-> ) engine = innodb;
Query OK, 0 rows affected (0.05 sec)
root@localhost [kris]> insert into b (bid) values (1), (2);
Query OK, 2 rows affected (0.00 sec)
Records: 2 Duplicates: 0 Warnings: 0
Operation 1: Selektion, Operation 2: Projektion. Auswahl von Zeilen und Spalten.
Die erste Operation ist die Selektion. Aus allen Zeilen einer Tabelle wählt die Selektion genaudie Tupel aus, für die die angegebene Bedingung, das angegebene Prädikat, wahr ist.
root@localhost [kris]> select aid from a where aid >= 2;
+-----+
| aid |
+-----+
| 2 |
| 3 |
+-----+
2 rows in set (0.00 sec)
Wir haben eine Relation: Die Ergebnismenge ist eine Teilmenge der Ausgangsmenge und kann
aus mehr als einem Tupel bestehen. Wir haben auch eine Algebra, jedenfalls hinsichtlich der
Selektion: Es wird eine Tabelle zurück geliefert.
Die zweite Operation ist die Projektion. Aus allen Tupeln der Tabelle werden neue Tupelberechnet. Die Abbildung kann die Identität sein ("select spaltenname ...") oder das Ergebnis
einer komplizierteren Funktion sein, die ein oder mehr Stellen aus dem alten Tupel als
Eingabeparameter nimmt ("select a+b ...").
root@localhost [kris]> select aid, aid*1.19 from a; +-----+----------+ | aid | aid*1.19 | +-----+----------+ | 1 | 1.19 | | 2 | 2.38 | | 3 | 3.57 | +-----+----------+ 3 rows in set (0.00 sec)
Operation 3: Der Join (Das Kreuzprodukt).
Die dritte Operation ist der Join oder das Kreuzprodukt. Es verknüpft zwei Tabellen so, daßjede Zeile aus der ersten Tabelle mit jeder Zeile aus der zweiten Tabelle kombiniert wird.
root@localhost [kris]> select aid, bid from a, b; +-----+-----+ | aid | bid | +-----+-----+ | 1 | 1 | | 1 | 2 | | 2 | 1 | | 2 | 2 | | 3 | 1 | | 3 | 2 | +-----+-----+ 6 rows in set (0.00 sec)
Zusammen mit der Selektion kann man so Tabellen sinnvoll miteinander verknüpfen ("select *
from c, d where c.cid = d.cid"), und mit ein wenig Evolution landet man dann bei derSchlüsselwortSchreibweise von Joins (seit 1992 üblich): "select * from c join d on c.cid = d.cid".Diese Schreibweise macht JoinBedingungen (ONClause) von einschränkenden Prädikaten(WHEREClause) unterscheidbar und ist die empfohlene Schreibweise für Joins.
Operation 4: Rename. Nützlich vor allen Dingen mit SelfJoins in Bäumen und Hierarchien.
Die vierte Operation ist der Rename mit dem Schlüsselwort AS. Man kann Tabellen und Spaltenumbenennen. Die RenameOperation erscheint sinnlos, ist aber zwingend notwendig, damit manselbstreferentielle Strukturen wie Bäume und Hierarchien abbilden kann.
root@localhost [kris]> create table emp (
-> empid integer unsigned not null,
-> bossid integer unsigned null
-> ) engine = innodb;
Query OK, 0 rows affected (0.06 sec)
root@localhost [kris]> insert into emp
-> values
-> ( 1, NULL),
-> (2, 1), (3,1),
-> (4, 2), (5, 2), (6, 2);
Query OK, 6 rows affected (0.00 sec)
Records: 6 Duplicates: 0 Warnings: 0
root@localhost [kris]> select * from emp join emp on emp.bossid = emp.empid;
ERROR 1066 (42000): Not unique table/alias: 'emp'
root@localhost [kris]> select
-> emp.empid as mitarbeiter,
-> " hat den Boss ",
-> boss.empid as boss
-> from
-> emp as boss join emp on emp.bossid = boss.empid;
+-------------+----------------+------+
| mitarbeiter | hat den Boss | boss |
+-------------+----------------+------+
| 2 | hat den Boss | 1 |
| 3 | hat den Boss | 1 |
| 4 | hat den Boss | 2 |
| 5 | hat den Boss | 2 |
| 6 | hat den Boss | 2 |
+-------------+----------------+------+
5 rows in set (0.34 sec)
Operation 5: Aggregation.
Und schließlich gibt es noch die Aggregation. Bei einem Aggregat hat man ein Tupel mit nStellen, zum Beispiel 2 Stellen und vertrachtet bei Vergleichen nur eine Stelle, etwa die erste,um das Ergebnis in Gruppen einzuteilen. Nehmen wir zum Beispiel noch einmal unsereMitarbeiterliste mit Bossen und Mitarbeitern:
root@localhost [kris]> select bossid, empid from emp; +--------+-------+ | bossid | empid | +--------+-------+ | NULL | 1 | | 1 | 2 | | 1 | 3 | | 2 | 4 | | 2 | 5 | | 2 | 6 | +--------+-------+ 6 rows in set (0.00 sec)
Hier haben wir einen Haufen 2Tupel. Betrachten wir nur die erste Spalte, dann haben wir eineGruppe von Mitarbeitern, die dem Boss 1 unterstellt sind, und eine Gruppe von Mitarbeitern, diedem Boss 2 unterstellt sind. In SQL:
root@localhost [kris]> select -> emp.bossid, -> count(*), -> group_concat(emp.empid) as mitarbeiter -> from -> emp -> group by -> emp.bossid; +--------+----------+-------------+ | bossid | count(*) | mitarbeiter | +--------+----------+-------------+ | NULL | 1 | 1 | | 1 | 2 | 2,3 | | 2 | 3 | 4,5,6 | +--------+----------+-------------+ 3 rows in set (0.00 sec)
GROUP BY macht genau diese Aggregation das Einteilen in Gruppen. In einer Query mitGROUP BY dürfen wir vorne im SELECTTeil nur Spalten erwähnen, die auch im GROUP BYTeil genannt sind, und Aggregatfunktionen. COUNT ist so eine Aggregatfunktion sie sagt uns,wie viele Elemente denn in der Gruppe (1, *) sind und wie viele in der Gruppe (2, *).GROUP_CONCAT ist eine weitere Funktion. Sie nimmt die Elemente der Gruppe und machteine KommaListe daraus.
Damit haben wir eine Algebra mit einer Grundmenge (Tupelmengen, also Tabellen) und fünfeinfachen Operationen, die Tabellen in andere Tabellen umwandeln.
Algebra bedeutet: weiterrechnen zu können
Da das ganze eine Algebra ist, heißt das: Wir können mit den Ergebnissen einer Operationweiter Rechnen, also errechnete Tabellen in SQLStatements einsetzen. Dieser Mechanismusheißt in SQL Subquery: Wir können an jeder Stelle eines SELECTStatements an der Stelle vonWerten oder Tabellen eine weitere SELECTQuery einsetzen. Wenn ein einzelner Wert verlangtwird, muß das eingesetzte SELECT ein skalares SELECT sein, also eine 1x1Tabelle zurückliefern.
Ein einfaches Beispiel:
root@localhost [kris]> select sum(bid) from b;
+----------+
| sum(bid) |
+----------+
| 3 |
+----------+
1 row in set (0.00 sec)
root@localhost [kris]> select aid, (
-> select sum(bid) from b ) as bsum
-> from a;
+-----+------+
| aid | bsum |
+-----+------+
| 1 | 3 |
| 2 | 3 |
| 3 | 3 |
+-----+------+
3 rows in set (0.03 sec)
Hier ist als Teil der SELECTClause statt einer Konstanten oder eines Spaltennamen einskalares SELECT eingesetzt worden. Die Spalte bsum ist das Ergebnis der Abfrage "selectsum(bid) from b" und wird dort eingesetzt.
Auch in der FROMClause eines SELECT kann man SELECTStatements einsetzen. DieseQuery zum Beispiel listet zu jedem Schema auf, wie viele Zeilen die größte Tabelle in diesemSchema hat:
root@localhost [test_world]> select
-> table_schema,
-> max(table_rows)
-> from
-> information_schema.tables
-> group by
-> table_schema;
+--------------------+-----------------+
| table_schema | max(table_rows) |
+--------------------+-----------------+
| geodb | 459015 |
| information_schema | NULL |
| kris | 6 |
| mysql | 986 |
| test | 12 |
| test_tablesizes | 79 |
| test_world | 4079 |
+--------------------+-----------------+
7 rows in set (3.92 sec)
Wenn wir nun den Namen der Tabelle ermitteln wollen, die in diesem Schema die meisten Zeilenhat, dann geht das unter anderem so:
root@localhost [test_world]> create table tables as
-> select * from information_schema.tables;
Query OK, 93 rows affected (1.12 sec)
Records: 93 Duplicates: 0 Warnings: 0
root@localhost [test_world]> select
-> m.table_schema,
-> t.table_name, -> m.maxrows -> from -> tables as t join -> (select table_schema, max(table_rows) as maxrows -> from tables group by table_schema ) as m -> on t.table_rows = m.maxrows; +-----------------+----------------+---------+ | table_schema | table_name | maxrows | +-----------------+----------------+---------+ | geodb | geodb_textdata | 466518 | | kris | emp | 6 | | mysql | help_relation | 986 | | test | h | 12 | | kris | p | 6 | | test | t | 12 | | test_tablesizes | sizes | 79 | | test_world | City | 4079 | +-----------------+----------------+---------+ 8 rows in set (0.00 sec)
In einem ersten Schritt machen wir hier einen Snapshot von information_schema.tables. Das istnicht nur schneller, sondern es bewirkt auch, daß wir statische Daten bekommen. Dadurchhaben zwei aufeinander folgende Anfragen an die Tabelle auch identische Werte das ist beiinformation_schema sonst nicht zwingend gegeben.
Die zweite Query setzt die Tabelle aus dem ersten Beispiel in der FROMClause ein und joinedsie gegen unseren information_schema Snapshot. Wir fragen nun nach dem Schema und demNamen der Tabelle, die dieselbe Größe hat, wie das in der Subquery ermittelte Maximum. Esgibt viele Wege, um dieses Problem 'Finde das gruppenweise Maximum' zu lösen JanKneschke hat eine Übersicht.
Auch in einer WHEREClause können wir eine Subquery einbauen. Gemäß dem Beispiel vonJan:
root@localhost [test_world]> select -> t.table_schema, -> t.table_name, -> t.table_rows -> from -> tables as t -> where -> t.table_rows = ( -> select max(table_rows) as maxrows -> from tables as m -> where -> t.table_schema = m.table_schema -> ); +-----------------+----------------+------------+ | table_schema | table_name | table_rows | +-----------------+----------------+------------+ | geodb | geodb_textdata | 466518 | | kris | emp | 6 | | mysql | help_relation | 986 | | test | h | 12 | | test | t | 12 | | test_tablesizes | sizes | 79 | | test_world | City | 4079 | +-----------------+----------------+------------+ 7 rows in set (0.00 sec)
Das liest sich als: Liste mir alle Tabellen mit ihrer Größe, bei denen die Größe der maximalenGröße der Tabelle entspricht, die im selben Schema ist wie die aktuelle Tabelle.
Weitere Anwendungsfälle von Subqueries finden sich im Beispiel von Jan und im Handbuch mir geht es hier in erster Linie darum zu zeigen, wie die AlgebraEigenschaft von SQL dasWeiterrechnen mit den Ergebnissen erlaubt.
Tupel als Datentyp
Tabellen sind Mengen von Tupeln, und Tupel sind ein Datentyp in SQL, mit dem man arbeitenkann. Mit der Tabelle
root@localhost [kris]> select * from t; +------+-------+------+ | a | b | c | +------+-------+------+ | eins | one | 1 | | zwei | two | 2 | | drei | three | 3 | | 1 | eins | one | +------+-------+------+ 4 rows in set (0.00 sec)
läßt sich die einfache Anfrage
root@localhost [kris]> select a,b,c from t where a = 'eins' and b = 'one'; +------+------+------+ | a | b | c | +------+------+------+ | eins | one | 1 | +------+------+------+ 1 row in set (0.00 sec)
auch so schreiben:
root@localhost [kris]> select a,b,c from t where (a,b) = ('eins','one'); +------+------+------+ | a | b | c | +------+------+------+ | eins | one | 1 | +------+------+------+ 1 row in set (0.00 sec)
Erweitert kann man auch nach mehr als einem Wert fragen:
root@localhost [kris]> select * from t where (a,b) in (('eins','one'), ('zwei', 'two')); +------+------+------+ | a | b | c | +------+------+------+ | eins | one | 1 | | zwei | two | 2 | +------+------+------+ 2 rows in set (0.00 sec)
Manchmal will man nach einem Wert in irgendeiner Spalte suchen:
root@localhost [kris]> select a,b,c from t -> where 'eins' in (a,b,c); +------+------+------+ | a | b | c | +------+------+------+ | eins | one | 1 | | 1 | eins | one | +------+------+------+ 2 rows in set (0.00 sec)
ist "Finde mir alle Zeilen, in denen in einer Spalte der Wert 'eins' vorkommt.". Auch das geht mitTupeln. In diesem Fall will ich, daß 'eins' und 'one' in benachbarten Spalten vorkommen:
root@localhost [kris]> select a,b,c from t -> where ('eins','one') in ((a,b),(b,c)); +------+------+------+ | a | b | c | +------+------+------+ | eins | one | 1 | | 1 | eins | one | +------+------+------+ 2 rows in set (0.00 sec)
Leider ist MySQL nicht ganz konsequent mit der Umsetzung von Tupeln als Datentyp: Man kannden Aufruf einer Stored Procedure ('CALL blah()') nicht in einer Subquery verwenden.
Abfragesprachen, die keine Algebra sind
Viele Abfragesprachen existieren, die keine Algebra sind, bei denen also die Ergebnisse nichtvon der Art sind, daß man mit ihnen weiter rechnen könnte.
Ein klassisches Beispiel ist LDAP: LDAP definiert Operationen auf einem Baum, dem LDAPBaum. Das Ergebnis einer LDAPQuery ist jedoch kein Teilbaum, sondern eine Knotenmenge.Diese kann mit LDAPOperationen nicht weiter verfeinert oder verarbeitet werden. Das Ergebnis:LDAPServer sind zwar sehr schnell und können zum Teil hunderttausende von Anfragen proSekunde verarbeiten. Aber Dinge, die man in SQL mit einer Query erledigen könnte brauchen inLDAP dann auch hunderttausende von Anfragen.
Ein weiteres klassisches Beispiel: XPath. XPath definiert ebenfalls einen Baum als Datentyp undOperationen darauf. Das Ergebnis einer XPathQuery ist jedoch ein Nodeset, kein Baum, kannalso mit XPath auch nicht weiter verarbeitet werden (aber XSLT ist sowieso so angelegt, daß derZugriff auf Ergebnisse zur Weiterverarbeitung mindestens stark erschwert wird, wenn nicht sogarunmöglich gemacht wird).
In beiden Fällen schränkt sich die Abfragesprache in ihren Möglichkeiten stark ein und erfordertdann mehr Code (und mehr Kommunikation, und damit mehr Latenz) in der Hostsprache, in dersie eingebettet ist.Geschrieben von Kristian Köhntopp in MySQL um 05:18 | Kommentare (9) | Trackbacks (2)
TrackbacksTrackbackURL für diesen Eintrag
Kris erklaert die Welt heute: Relationale AlgebraKris hat einen tollen Artikel über relationale Algebra geschrieben. Hochinteressant und eineeindeutige Leseempfehlung: Was bedeutet eigentlich 'Relationale Algebra'? Insbesondere gefälltmir:Das ist genug Mathematik. Wir wollen Informatik machen. DasWeblog: c0t0d0s0.orgAufgenommen: Apr 28, 10:29
SQL aus einer anderen SichtIhr werdet alle SQL kennen und auch einsetzen koennen, aber dieser ("Was bedeutet eigentlichRelationale Algebra") Artikel ist wirklich gut gemacht. Es wird SQL aus Sicht der Mathematikerklaert. Der richtig Interessante Teil beginnt ab Das ist genug MaWeblog: SHC InternAufgenommen: Apr 28, 11:25
KommentareAnsicht der Kommentare: (Linear | Verschachtelt)
Mit XSLT liegst Du übrigens falsch, Nodesets sind durchaus noch Bäume:
vb@bayhorse:~ % cat a.xmlblubvb@bayhorse:~ % cat b.xsl
vb@bayhorse:~ % xsltproc b.xsl a.xml
blubvb@bayhorse:~ %
Die Abfragemächtigkeit von XPath entspricht der von SQL, zur Einbettung gibt es sowohl schnelleals auch einfache Implementierungen. Schau Dir mal libxslt an.
Viele Grüsse,
VB.
#1 Volker Birk (Link) am 28.04.2010 10:50
Oh, da hats alles, was eine Spitze Klammer hat, weggenommen ;)
Ich versuche mal, das gequotet zu bringen:
vb@bayhorse:~ % sed e 's//?/g' a.xml
?x? ?y? ?z? blub ?/z? ?/y? ?/x?
vb@bayhorse:~ % sed e 's//?/g' b.xsl
?xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"?
?xsl:template match="/"?
?xsl:calltemplate name="f"?
?xsl:withparam name="a" select="x" /?
?/xsl:calltemplate?
?/xsl:template?
?xsl:template name="f"?
?xsl:param name="a" /?
?xsl:copyof select="$a/y/*" /?
?/xsl:template?
?/xsl:stylesheet?
vb@bayhorse:~ % xsltproc b.xsl a.xml | sed e 's//?/g'
??xml version="1.0"??
?z? blub ?/z?
vb@bayhorse:~ %
#2 Volker Birk (Link) am 28.04.2010 10:54
Das ist sehr schwer, BBCode wehrt sich echt ernsthaft gegen XSS. :)
Die Frage ist letztendlich, ob man das Ergebnis einer XPathQuery in eine XPathQuery
einsetzen kann, also ob es XPath Subqueries gibt. Wenn ja, dann hast Du eine Algebra, sonst
nicht.
Und soweit ich weiß, hat XPath 1.0 ohne VendorExtension diese Möglichkeit nicht. Wie auch
XSLT den Quellbaum und den Zielbaum voneinander trennt, sodaß man nicht innerhalb
derselben XSLTTransformationsvorschrift auf das Ergebnis der XSLT
Transformationsvorschrift zugreifen kann.
#2.1 Isotopp (Link) am 28.04.2010 11:04
Antwort der mich umgebenden XPathExperten: Es geht nicht direkt, nur über das Speichern
der Ergebnisse in Variablen (die man dann wieder mit XPath verarbeiten kann).
#2.1.1 Martin (Link) am 28.04.2010 11:45
Aber genau das mache ich doch im Beispiel oben.
Die erste Query ist "a", die zweite ist "$a/y/*".
Mit der zweiten kopiere ich besagten Teilbaum, das sieht man dann am Ergebnis, wenn
mans ausführt.
Viele Grüsse,
VB.
#2.1.2 Volker Birk (Link) am 29.04.2010 11:18
Und sauber das distinctProblem umschifft. :) In einem wirklich relationalen SQL ist DISTINCT
implizit, wobei ich zugegebenerweise keine Ahnung haben, was aktuelle Datenbanken dazu
meinen.
#3 Andreas Krey (Link) am 28.04.2010 18:32
Für distinct gibt's EXSLT oder eben XPath 2.0.
Viele Grüsse,VB.#3.1 Volker Birk (Link) am 29.04.2010 11:20
Vielen Dank für den schnellen Überblick.Eine Anmerkung:Für Einsteiger ist nicht ersichtlich, dass Funktionen wie GROUP_CONCAT nicht allgemeinimplementiert sind, genauso wenig wie die TupelOperationen" ... where ('foo','bla') in ((a,b),(b,c))"
Gruß#4 srm am 05.05.2010 00:36
Ich lese derzeit "SQL and Relational Theory" von C.J. Date (das ist der mit dem "Third Manifesto")und kann das nur empfehlen, wenn man einen Überblick über relationale Algebra haben möchte.
Mittlerweile glaube ich, daß es am besten ist, erstmal nur die allerflachsten Grundlagen von SQLzu lernen (wie mache ich eine einfache Query mit SELECT, WHERE und GROUP BY), danndieses Buch zu lesen, um erstmal zu verstehen, was man später tun wird, und danach erst einechtes SQLLehrbuch zur Hand zu nehmen.
Dann weiß man nämlich beim Lernen von SQL gleich, wo man von der relationalen Theorieabweicht und was das für Folgen hat.#5 Thomas Hühn (Link) am 25.07.2010 06:49
Kommentar schreibenName
EMail
Homepage
Antwort zu
Kommentar
Umschließende Sterne heben ein Wort hervor (*wort*), per _wort_ kann ein Wortunterstrichen werden.
Um maschinelle und automatische Übertragung von Spamkommentaren zuverhindern, bitte die Zeichenfolge im dargestellten Bild in der Eingabemaskeeintragen. Nur wenn die Zeichenfolge richtig eingegeben wurde, kann derKommentar angenommen werden. Bitte beachten Sie, dass Ihr Browser Cookiesunterstützen muss, um dieses Verfahren anzuwenden.
Hier die Zeichenfolge der SpamschutzGrafik eintragen:
BBCodeFormatierung erlaubt Daten merken?
top related