MySQL "WITH" -Klausel

97

Ich versuche, mit MySQL eine Ansicht mit der "WITH" -Klausel zu erstellen

WITH authorRating(aname, rating) AS
   SELECT aname, AVG(quantity)
   FROM book
   GROUP BY aname

MySQL scheint dies jedoch nicht zu unterstützen.

Ich fand das ziemlich normal und bin mir sicher, dass Oracle dies unterstützt. Gibt es überhaupt eine Möglichkeit, MySQL zu zwingen, die "WITH" -Klausel zu verwenden? Ich habe es mit der MyISAM- und innoDB-Engine versucht. Beide funktionieren nicht.

shA.t.
quelle

Antworten:

109

Update: MySQL 8.0 erhält endlich die Funktion allgemeiner Tabellenausdrücke, einschließlich rekursiver CTEs.

Hier ist ein Blog, der dies ankündigt: http://mysqlserverteam.com/mysql-8-0-labs-recursive-common-table-expressions-in-mysql-ctes/

Unten ist meine frühere Antwort, die ich ursprünglich 2008 geschrieben habe.


MySQL 5.x unterstützt keine Abfragen mit der WITHin SQL-99 definierten Syntax, auch Common Table Expressions genannt.

Dies ist seit Januar 2006 eine Funktionsanforderung für MySQL: http://bugs.mysql.com/bug.php?id=16244

Andere RDBMS-Produkte, die allgemeine Tabellenausdrücke unterstützen:

Bill Karwin
quelle
1
SQLite unterstützt die WITH-Klausel ab Version 3.8.3, die am 03.02.2014 veröffentlicht wurde.
Martijn
Ich habe H2 und Firebird zur Liste hinzugefügt.
a_horse_with_no_name
2
@ BillKarwin: Ich glaube nicht, dass MySQL jemals eine moderne DBMS-Funktion implementieren wird (Einschränkungen überprüfen, Fensterfunktion, Index für Ausdrücke, Teilindex, zurückgestellte Einschränkungen ...).
a_horse_with_no_name
2
@a_horse_with_no_name, sie scheinen der Skalierbarkeit eine viel höhere Priorität einzuräumen. Sie haben sich lange darauf konzentriert, ihre Interna skalierbarer zu machen, um die Vorteile moderner Hardware zu nutzen. Aber ich denke, sie haben SQL-Funktionen vernachlässigt.
Bill Karwin
1
@BlakeMcBride, du liegst falsch, dein Kommentar ist FUD und hat tatsächlich keine Grundlage. Oracle besitzt auch andere Datenbankprodukte, die Dinge tun, die Oracle DB nicht gut macht. Beispiele: TimesTen, BerkeleyDB. Sie haben diese Datenbanken erworben, um ihren Markt zu erweitern. MySQL ist auf dem Markt für Webanwendungen dominant, Oracle DB nicht. Daher haben sie MySQL erworben. Für Oracle macht es keinen Sinn, MySQL zu behindern. Ich habe auf der Konferenz im April mit den Oracle MySQL-Entwicklern gesprochen, und sie arbeiten tatsächlich an der Implementierung von WITH für MySQL.
Bill Karwin
17

Sie könnten an so etwas interessiert sein:

select * from (
    select * from table
) as Subquery
Mosty Mostacho
quelle
Können Sie bitte die Unterabfrage erklären? Könnte ich * aus ((* aus Tabelle1 auswählen)) UNION ALL (* aus Tabelle2 auswählen)) Gruppe nach etwas auswählen?
1
@Kathy Hallo, Subqueryist der Name, den ich für die abgeleitete Tabelle selbst verwendet habe. Wenn Sie verwenden from ( ... ), erstellen Sie so etwas wie eine temporäre Tabelle (eine abgeleitete Tabelle) und es erfordert einen Namen. Deshalb habe ich verwendet as Subquery. Wenn Sie Ihre Frage beantworten, können Sie dies, aber Sie müssen der äußeren abgeleiteten Tabelle (kurz vor dem Group By) einen Namen geben . Hoffe das hat geholfen.
Mosty Mostacho
@MostyMostacho Hallo, könntest du mich bitte hier ein wenig mit dem Löffel füttern? Ich habe Probleme, es in MySQL zu konvertieren. Kannst du dir das mal anschauen? Link oder beantworte meine Frage hier vielleicht? Link
Pranav
13

Sie haben die richtige Syntax:

WITH AuthorRating(AuthorName, AuthorRating) AS
   SELECT aname         AS AuthorName,
          AVG(quantity) AS AuthorRating
   FROM Book
   GROUP By Book.aname

Wie bereits erwähnt, unterstützt MySQL diesen Befehl jedoch nicht. WITH wurde in SQL hinzugefügt: 1999; Die neueste Version des SQL-Standards ist SQL: 2008. Weitere Informationen zu Datenbanken, die die verschiedenen Funktionen von SQL: 1999 unterstützen, finden Sie auf Wikipedia .

MySQL ist bei der Unterstützung des SQL-Standards traditionell etwas zurückgeblieben, während kommerzielle Datenbanken wie Oracle, SQL Server (vor kurzem) und DB2 ihnen etwas genauer gefolgt sind. PostgreSQL ist normalerweise auch ziemlich standardkonform.

Vielleicht möchten Sie sich die Roadmap von MySQL ansehen. Ich bin mir nicht ganz sicher, wann diese Funktion unterstützt wird, aber sie eignet sich hervorragend zum Erstellen lesbarer Rollup-Abfragen.

Ed Altorfer
quelle
8

Oracle unterstützt WITH.

Es würde so aussehen.

WITH emps as (SELECT * FROM Employees)
SELECT * FROM emps WHERE ID < 20
UNION ALL
SELECT * FROM emps where Sex = 'F'

@ysth WITH ist schwer zu googeln, da es sich um ein allgemeines Wort handelt, das normalerweise von der Suche ausgeschlossen wird.

Sie sollten sich die SELECT-Dokumente ansehen, um zu sehen, wie das Factoring von Unterabfragen funktioniert.

Ich weiß, dass dies das OP nicht beantwortet, aber ich räume alle Verwirrungen auf, die möglicherweise begonnen haben.


quelle
Hat meine Verwirrung sowieso nicht geklärt. Wollen Sie damit sagen, dass es keine WITH-Klausel gibt, aber eine WITH-Anweisung?
ysth
1
Ah ich sehe. Es ist eine Klausel einer Auswahl, die der Auswahl vorausgeht. Kann es auch in CREATE VIEW verwendet werden? Wie unterscheidet es sich vom Beitritt zu einer Unterauswahl? Ich sehe online keine Beispiele, bei denen der Name nach dem WITH Parameter enthält - wie funktionieren diese?
ysth
1
Es ist ganz anders. Beachten Sie, dass derselbe Subqry zweimal verwendet wird, ohne ihn zweimal definieren zu müssen. Sicher, Sie könnten dieselbe Abfrage dort kopieren / einfügen, aber dies ist ein einfaches Beispiel. Stellen Sie sich vor, die WITH-Klausel wurde für eine Seite verwendet und in der Hauptabfrage viermal verwendet. Sie werden es dann zu schätzen wissen.
Ich habe auf die Dokumente verlinkt, die die Syntax erklären sollten. Soweit in einer Ansicht. Sicher funktioniert es dort.
2

Aufbauend auf der Antwort von @Mosty Mostacho können Sie in MySQL Folgendes tun, um festzustellen, welche Einträge in einer Tabelle nicht vorhanden sind und sich in keiner anderen Datenbank befinden.

select col1 from (
   select 'value1' as col1 union
   select 'value2' as col1 union
   select 'value3' as col1
) as subquery
left join mytable as mytable.mycol = col1
where mytable.mycol is null
order by col1

Möglicherweise möchten Sie einen Texteditor mit Makrofunktionen verwenden, um eine Liste von Werten in die angegebene select union-Klausel zu konvertieren.

Ruben
quelle
1
   WITH authorRating as (select aname, rating from book)
   SELECT aname, AVG(quantity)
   FROM authorRating
   GROUP BY aname
Mantas Dainys
quelle
0

Haben Sie schon einmal Temporary Table ausprobiert? Dies löste meine Convern:

create temporary table abc (
column1 varchar(255)
column2 decimal
);
insert into abc
select ...
or otherwise
insert into abc
values ('text', 5.5), ('text2', 0815.8);

Dann können Sie diese Tabelle in jeder Auswahl in dieser Sitzung verwenden:

select * from abc inner join users on ...;
Claus
quelle
1
Ich muss beachten: stackoverflow.com/questions/343402/… Sie können Tabelle nicht zweimal öffnen :-(
Claus
Meine Sollution für kleine Datensätze in Tabellen: Erstelle Tabelle abc2 wie abc; in abc2 einfügen select * from abc;
Claus