SQL - Group By içinde takma ad kullanma


143

Sadece SQL sözdizimini merak ediyorum. Eğer varsa

SELECT 
 itemName as ItemName,
 substring(itemName, 1,1) as FirstLetter,
 Count(itemName)
FROM table1
GROUP BY itemName, FirstLetter

Bu yanlış olur çünkü

GROUP BY itemName, FirstLetter 

gerçekten olmalı

GROUP BY itemName, substring(itemName, 1,1)

Ama neden eskisini kolaylık sağlamak için kullanamıyoruz?



7
MySQL de izin veriyor
Kip

1
hangi rdbms'den bahsediyorsun?
Shiwangini

Yanıtlar:


292

SQL, bir sorgu aşağıdaki sırada yürütülmüş gibi uygulanır:

  1. FROM yan tümcesi
  2. NEREDE yan tümcesi
  3. GROUP BY deyimi
  4. HAVING cümlesi
  5. SELECT cümlesi
  6. ORDER BY deyimi

İlişkisel veritabanı sistemlerinin çoğunda, bu sipariş hangi adların (sütunlar veya takma adlar) geçerli olduğunu açıklar, çünkü önceki bir adımda sunulmaları gerekir.

Bu nedenle Oracle ve SQL Server'da, GROUP BY deyiminden önce GROUP BY deyiminden önce SELECT deyiminde tanımladığınız bir terimi kullanamazsınız.

Yine de istisnalar var: MySQL ve Postgres buna izin veren ek bir akıllılığa sahip gibi görünüyor.


3
Bu açıklamayı seviyorum. Her ne kadar sözdizimsel şeker olarak bir motora eklemenin ne kadar zor olduğunu tahmin edemem.
Haoest

11
DB aynı ifadeyi gerçekleştirecek kadar akıllıysa, ifadeleri yeniden değerlendirmeden SELECT ve GROUP BY deyimlerinde bulunur mu? yani varsa GROUP BY substring(itemName, 1,1), veritabanı SELECT yan tümcesinde alt dizeyi yeniden hesaplama performans isabet almak için yeterince akıllı mı?
Kip

10
Gruplama içeren bir sorgunun SELECT yan tümcesinde, yalnızca GROUP BY ifadelerine ve toplanmış değerlere erişebilirsiniz. Yani akıllı olmakla ilgili değil; gruplamanın çalışması için bu şekilde uygulanmalıdır. (Ve SQL standardı tarafından gereklidir). Ancak daha önemsiz durumlarda bile (örneğin, WHERE ve SELECT yan tümcesinde aynı ifade), en son teknoloji veritabanı sistemleri bunu yalnızca bir kez hesaplayacaktır. Bu optimizasyona ortak alt ifade eliminasyonu denir .
Codo

6
İcra emrinin bu soru ile ne ilgisi var? Asker COUNT () üzerinden GROUP BY yapmaya çalışıyor gibi değil. Aslında, sorulduğu gibi sorgu MySQL ve muhtemelen PostgreSQL yorumlarda işaret gibi iyi çalışıyor.

1
MySQL için, sql_modedahil değil ONLY_FULL_GROUP_BY bit maskesi, Doktoru yayınlama şansına sahip daha iyi sonuçlar bir değişiyordu / ile farklı takma ad kullanımı HAVINGmaddesi.
Drew

28

Diğer adı kullanmak için her zaman bir alt sorgu kullanabilirsiniz; Tabii ki, performansı kontrol edin (Olası db sunucusu her ikisini de çalıştıracak, ancak doğrulamak için asla acı vermiyor):

SELECT ItemName, FirstLetter, COUNT(ItemName)
FROM (
    SELECT ItemName, SUBSTRING(ItemName, 1, 1) AS FirstLetter
    FROM table1
    ) ItemNames
GROUP BY ItemName, FirstLetter

2
Kötü performans nedeniyle mümkün olduğunca alt sorgulardan kaçınılmalıdır. Tabii ki veritabanı en iyi duruma getiricisi tarafından algılanması ve yalnızca bir kez yapılması nedeniyle işlevin bir kopyasını kullanmak çok daha iyidir.
Roland

1
@Roland ama bu durumda uygulama planında farklı değil. Başka bir performans değerlendirmesi var mı?
Guido Mocha

@Roland, İlişkili alt sorgular veya döngülere veya satır satır davranışa yol açan diğer sözdiziminden kaçınılmalıdır ve iç içe geçmiş sorgularla ne kadar derin gitmeniz gerektiğine ilişkin bir sınır vardır, ancak genellikle alt sorguların yönlendirdiği doğru değildir kötü performans. Bu durumda Chris'in dediği gibi, yürütme planını (AKA sorgu planı, açıklama planı) hem alt sorgu ile hem de alt sorgu ile karşılaştırarak doğrulayabilir ve gerçekten herhangi bir fark olup olmadığını görebilirsiniz. Hemen hemen her veritabanı motoru sorgunuzu yeniden yazacak, böylece ne yürütüldüğünün tamamen kontrolü sizde değil. Bu, bildirici sözdiziminin noktasıdır.
Davos

16

En azından PostgreSQL'de GROUP BY deyiminizdeki sonuç kümesindeki sütun numarasını kullanabilirsiniz:

SELECT 
 itemName as ItemName,
 substring(itemName, 1,1) as FirstLetter,
 Count(itemName)
FROM table1
GROUP BY 1, 2

Elbette, bunu etkileşimli olarak yapıyorsanız ve sonuçtaki sütun sayısını veya sırasını değiştirmek için sorguyu düzenlerseniz bu bir acı olmaya başlar. Ama hala.


GROUP BY FirstLetterPostgresql'de izin verilir. Zekâ için, bunu Postgresql'de çalıştırmayı deneyin: tname'ye göre information_schema.tables grubundan alt dize (table_name, 1,2) tname olarak seçin
Michael Buen

1
@MichaelBuen Benim için potansiyel olarak sorunlu görünüyor. Hızlı bir testten, aynı ada sahip bir takma ad ve bir temel tablo sütunu varsa, ikincisi öncelik kazanıyor gibi görünüyor? SQL Fiddle . Bu nedenle, bu gruba diğer adla güveniyorsanız, daha sonraki bir şema değişikliği sessizce sorgunuzu kırabilir ve anlambilimi değiştirebilir.
Martin Smith

@MartinSmith sadece şimdi bir gotcha olduğunu biliyordu, bunu kullanmaktan kaçınacak, teşekkürler. PostgreSQL'in bu kısayola izin verdiği göz önüne alındığında, takma ada bir öncelik vermeli, aksi takdirde bu kısayola hiç izin vermemelidir.
Michael Buen

Bu, PostgreSQL tasarımcıları tarafından korkunç bir fikirdi. GROUP BYToplama işlevlerini veya pencere işlevlerini içeren ve "açıkça" çalışmayan herhangi bir ifadeyi denediğinizde kafa karıştırıcıdır .
Lukas Eder

13

SQL Server, mantıksal işlem sırası nedeniyle GROUP BY yan tümcesindeki diğer adı başvurmanıza izin vermez. GROUP BY yan tümcesi SELECT yan tümcesinden önce işlenir, bu nedenle GROUP BY yan tümcesi değerlendirildiğinde diğer ad bilinmez. Bu aynı zamanda ORDER BY deyimindeki diğer adı neden kullanabileceğinizi de açıklar.

İşte SQL Server mantıksal işlem aşamaları hakkında bilgi için bir kaynak .


8

Neden böyle olduğunu yanıtlamıyorum, ancak yalnızca CROSS APPLYtakma ad oluşturmak için kullanarak SQL Server'da bu sınırlama etrafında bir yol göstermek istedim . Daha sonra GROUP BYmaddede kullanıyorsunuz, şöyle:

SELECT 
 itemName as ItemName,
 FirstLetter,
 Count(itemName)
FROM table1
CROSS APPLY (SELECT substring(itemName, 1,1) as FirstLetter) Alias
GROUP BY itemName, FirstLetter

4

Group By içinde takma ad kullanmanın (postgres gibi onu destekleyen hizmetler için) istenmeyen sonuçlara yol açabileceğine dikkat edin. Örneğin, iç ifadede zaten var olan bir takma ad oluşturursanız, Gruplama ölçütü iç alan adını seçer.

-- Working example in postgres
select col1 as col1_1, avg(col3) as col2_1
from
    (select gender as col1, maritalstatus as col2, 
    yearlyincome as col3 from customer) as layer_1
group by col1_1;

-- Failing example in postgres
select col2 as col1, avg(col3)
from
    (select gender as col1, maritalstatus as col2,
    yearlyincome as col3 from customer) as layer_1
group by col1;

3

Bazı DBMS'ler, tüm ifadeyi tekrarlamak yerine bir takma ad kullanmanıza izin verir.
Teradata böyle bir örnektir.

Belgelerde belirtilen nedenlerden dolayı Bill tarafından önerildiği üzere sıralı konum göstermekten kaçınırım Bu SO sorusunda .

Kolay ve sağlam alternatif, ifadeyi her zaman GROUP BY deyiminde tekrarlamaktır.
KURU SQL için geçerli DEĞİLDİR.


1

Sonuçları SQLite'ta bir görünümden gruplarken takma adlar kullanmaya dikkat edin. Takma ad, temel tabloların (görünümlere) sütun adıyla aynı ise beklenmedik sonuçlar alırsınız.


0

O günlerde Oracle tarafından desteklenen eski DEC ürünü Rdb'nin, GROUP BY'de sütun takma adının kullanılmasına izin verdiğini buldum. Sürüm 11 aracılığıyla Oracle'ın genel kullanımı, GROUP BY'de sütun diğer adının kullanılmasına izin vermez. Hangi Postgresql, SQL Server, MySQL, vb. İzin verir veya vermeyecektir emin değilim. YMMV.

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.