MySQL "WITH" cümlesi


98

"WITH" cümlesiyle bir görünüm oluşturmak için MySQL kullanmaya çalışıyorum

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

Ancak MySQL bunu desteklemiyor gibi görünüyor.

Bunun oldukça standart olduğunu düşündüm ve Oracle'ın bunu desteklediğinden eminim. MySQL'i "WITH" cümlesini kullanmaya zorlamanın bir yolu var mı? MyISAM ve innoDB motoru ile denedim. Bunların ikisi de çalışmıyor.

Yanıtlar:


109

Güncelleme: MySQL 8.0 nihayet özyinelemeli CTE'ler de dahil olmak üzere yaygın tablo ifadelerinin özelliğini alıyor.

İşte bunu duyuran bir blog: http://mysqlserverteam.com/mysql-8-0-labs-recursive-common-table-expressions-in-mysql-ctes/

Aşağıda, 2008'de yazdığım önceki cevabım var.


MySQL 5.x, Ortak Tablo İfadeleri olarakWITH da adlandırılan SQL-99'da tanımlanan sözdizimini kullanan sorguları desteklemez .

Bu, Ocak 2006'dan beri MySQL için bir özellik isteğidir: http://bugs.mysql.com/bug.php?id=16244

Yaygın tablo ifadelerini destekleyen diğer RDBMS ürünleri:


1
SQLite destekler İLE maddesini itibariyle sürümü 3.8.3 2014-02-03 tarihinde yayınladı.
Martijn

Listeye H2 ve Firebird ekledim.
a_horse_with_no_name

2
@BillKarwin: MySQL'in herhangi bir modern DBMS özelliğini hiçbir zaman uygulayacağına inanmıyorum (kısıtlamaları kontrol et, pencere işlevi, ifadeler üzerindeki indeks, kısmi indeks, ertelenmiş kısıtlamalar ...).
a_horse_with_no_name

2
@a_horse_with_no_name, ölçeklenebilirliğe çok daha yüksek bir öncelik veriyor gibi görünüyorlar. Modern donanımlardan yararlanmak için uzun süredir dahili bileşenlerini daha ölçeklenebilir hale getirmeye odaklanmışlardır. Ancak SQL özelliklerini ihmal ettiklerini düşünüyorum.
Bill Karwin

1
@BlakeMcBride, Yanılıyorsunuz, yorumunuz FUD ve aslında hiçbir temeli yok. Oracle ayrıca Oracle DB'nin iyi yapmadığı şeyleri yapan başka veritabanı ürünlerine de sahiptir. Örnekler: TimesTen, BerkeleyDB. Pazarlarını genişletmek için bu veritabanlarını aldılar. MySQL, web uygulama pazarında baskındır ve Oracle DB değildir, bu yüzden MySQL'i satın aldılar. Oracle'ın MySQL'i hamstring yapmasının bir anlamı yok. Nisan ayındaki konferansta Oracle MySQL geliştiricileriyle konuştum ve aslında MYSQL için WITH uygulaması üzerinde çalışıyorlar.
Bill Karwin

17

Bunun gibi bir şey ilginizi çekebilir:

select * from (
    select * from table
) as Subquery

Alt Sorguyu açıklar mısınız lütfen? ((tablo1'den * seçin) BİRLİĞİ TÜMÜ (tablo2'den * seçin)) arasından * seçimini yapabilir miyim?

1
@Kathy Merhaba, Subquerytüretilmiş tablonun kendisi için kullandığım isim. Kullandığınızda from ( ... ), geçici bir tablo (türetilmiş tablo) gibi bir şey yaratırsınız ve bir ad gerektirir. Bu yüzden kullandım as Subquery. Sorunuza cevap verirseniz, evet, yapabilirsiniz, ancak dıştaki türetilmiş tabloya bir isim koymanız gerekir (hemen önüne Group By). Umarım yardımcı olmuştur.
Mosty Mostacho

@MostyMostacho Merhaba, lütfen beni burada biraz kaşıkla besleyebilir misin? MySQL'e dönüştürmek için uğraşıyorum. Şuna bir bakar mısın? bağlantı veya sorumu burada cevaplayabilir miyim? bağlantı
Pranav

13

Sözdizimini doğru yaptınız:

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

Ancak, diğerlerinin de bahsettiği gibi, MySQL bu komutu desteklemiyor. C SQL'de eklendi: 1999; SQL standardının en yeni sürümü SQL: 2008'dir. SQL: 1999'un çeşitli özelliklerini destekleyen veritabanları hakkında daha fazla bilgiyi Wikipedia'da bulabilirsiniz .

MySQL geleneksel olarak SQL standardını desteklemek konusunda biraz geride kalmışken, Oracle, SQL Server (son zamanlarda) ve DB2 gibi ticari veritabanları onları biraz daha yakından takip ediyor. PostgreSQL tipik olarak oldukça standartlarla uyumludur.

MySQL'in yol haritasına bakmak isteyebilirsiniz; Bu özelliğin ne zaman destekleneceğinden tam olarak emin değilim, ancak okunabilir kapsamlı sorgular oluşturmak için harika.


11

Oracle, İLE'yi destekler.

Böyle görünürdü.

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

@ysth WITH, genellikle aramalardan hariç tutulan yaygın bir kelimedir çünkü google zordur.

Alt sorgu faktörlemesinin nasıl çalıştığını görmek için SELECT dokümanlarına bakmak istersiniz .

Bunun OP'ye cevap vermediğini biliyorum, ancak ysth'nin başlamış olabileceği herhangi bir karışıklığı temizliyorum.


Zaten kafa karışıklığımı çözmedi. Bir WITH cümlesi olmadığını ama bir WITH ifadesi olduğunu mu söylüyorsunuz?
ysth

1
Ah, anlıyorum. Seçimden önce gelen bir seçim cümlesi. CREATE VIEW'de de kullanılabilir mi? Bir alt seçime katılmanın farkı nedir? WITH'den sonraki adın parametrelere sahip olduğu çevrimiçi örnekler görmüyorum - bunlar nasıl çalışır?
ysth

1
Çok farklı. Aynı alt sorgunun, iki kez tanımlamak zorunda kalmadan iki kez kullanıldığına dikkat edin. Elbette aynı sorguyu oraya kopyalayabilir / yapıştırabilirsiniz, ancak bu basit bir örnek. WITH yan tümcesinin bir sayfa için devam ettiğini ve ana sorguda 4 kez kullanıldığını düşünün. o zaman takdir edeceksin.

Sözdizimini açıklamak için dokümanlar ile bağlantı kurdum. Bir bakış açısına kadar. Elbette orada çalışıyor.

3

@Mosty Mostacho'nun cevabına dayanarak, bir tabloda hangi girişlerin bulunmadığını ve başka herhangi bir veritabanında bulunmadığını belirleyen belirli bir durum için MySQL'de eşdeğer bir şeyi nasıl yapabileceğiniz aşağıda açıklanmıştır.

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

Bir değerler listesini alıntılanan seçme birleşim cümlesine dönüştürmek için makro yeteneklerine sahip bir metin düzenleyici kullanmak isteyebilirsiniz.



1
   WITH authorRating as (select aname, rating from book)
   SELECT aname, AVG(quantity)
   FROM authorRating
   GROUP BY aname

0

Hiç Geçici Masa denediniz mi? Bu benim convern'ımı çözdü:

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);

Daha sonra bu tabloyu bu oturumdaki her seçimde kullanabilirsiniz:

select * from abc inner join users on ...;

1
Unutmam gereken: stackoverflow.com/questions/343402/… Tabloyu iki kez açamazsınız :-(
Claus

Tablolardaki küçük veri kümeleri için Çözümüm: abc gibi abc2 tablosu oluşturun; abc2'ye ekleyin, abc'den * seçin;
Claus
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.