SQL'de iç içe geçmiş ve bağlantılı alt sorgular, EXISTS yüklemi. EXISTS operatörünü kullanma Mevcut işlevi kullanarak sorgular

NEREDE VAR

Alt sorguda bir veya daha fazla satırın olup olmadığı kontrol edilir. En az bir satır sorguyla eşleşiyorsa TRUE boolean değeri döndürülür. İsteğe bağlı NOT anahtar sözcüğü belirtildiğinde, alt sorgu eşleşen herhangi bir satır döndürmezse TRUE Boolean değeri döndürülür.

alt sorgu

Tamamen oluşturulmuş alt sorguya dayanarak elde edilen veri seti alınır.

Genel kurallar

EXISTS operatörü, bir üst sorgunun alt sorgusunda bir veya daha fazla satırın varlığını test eder.

SELECT * FROM NEREDE OLMAYAN işlerden (SELECT * FROM çalışandan WHERE jobs.job_id=employye.job_id);

Bu örnek, ek NOT anahtar sözcüğünü kullanarak kayıt alt sorgusunu kontrol eder. Aşağıdaki örnek, ana sonuç kümesini almak için bir alt sorgudaki belirli kayıtları arar.

SELECT au_lname FROM yazarlardan NEREDE MEVCUTTUR (SELECT * FROM yayıncılardan NEREDE yazarlar.city=publishers.city);

Bu sorgu, yayıncılarla aynı şehirde yaşayan yazarların (au_lname) soyadlarını döndürür. Alt sorgunun TRUE boolean değerine sahip yalnızca bir kayıt döndürmesi gerektiğinden, alt sorguda yıldız işareti kullanabileceğinizi unutmayın. Bu gibi durumlarda sütunların önemi yoktur. Anahtar nokta dizenin varlığıdır.

Birçok sorguda EXISTS operatörü, ANY ile aynı işlevi gerçekleştirir. EXISTS operatörü genellikle ilişkili sorgularla kullanıldığında en verimli sonucu verir.

EXISTS operatörü anlamsal olarak ANY operatörüne eşdeğerdir.

EXISTS deyimindeki bir alt sorgu genellikle iki tür aramadan birini gerçekleştirir. İlk seçenek bir joker karakter (yıldız işareti) kullanmaktır (örneğin, SELECT * FROM...), bu durumda herhangi bir belirli sütunu veya değeri almazsınız. Buradaki yıldız işareti "herhangi bir sütun" anlamına gelir. İkinci seçenek, alt sorguda yalnızca belirli bir sütunu seçmektir (örneğin, SELECT aujd FROM). Bazı bireysel platformlar, birden fazla sütunda alt sorgulara izin verir (örneğin, SELECT aujd, aujname FROM...). Ancak bu özellik nadirdir ve diğer platformlara taşınması gereken kodlarda kaçınılmalıdır.

Platformlar arasındaki farklar

Tüm platformlar yukarıda anlattığımız biçimde EXISTS operatörünü desteklemektedir.

"Önceden daha kolaydı" — SQL'deki bir sonraki sorguyu optimize etmek için oturduğumda düşündüm yönetim stüdyosu. MySQL altında yazdığımda her şey gerçekten daha basitti; ya çalışıyor ya da çalışmıyor. Ya yavaşlar ya da yavaşlamaz. Açıklama tüm sorunlarımı çözdü, daha fazlasına gerek yoktu. Artık sorguları ve prosedürleri/işlevleri geliştirmek, hata ayıklamak ve optimize etmek için güçlü bir ortama sahibim ve tüm bu dağınıklık bence yalnızca daha fazla sorun yaratıyor. Peki neden hepsi? Çünkü yerleşik sorgu iyileştirici kötüdür. Eğer MySQL ve PostgreSQL'de yazıyorsam

a, b, c arasından * seçin; burada a.id = b.id, b.id = c.id

ve tabletlerin her birinde en az 5k satır olacak - her şey donacak. Ve Tanrıya şükür! Çünkü aksi takdirde geliştirici, en iyi ihtimalle doğru yazmak için tembellik geliştirir ve en kötü ihtimalle ne yaptığını hiç anlamaz! Sonuçta MSSQL'deki aynı sorgu benzer şekilde çalışacaktır

a.id = b.id üzerinde bir birleştirme b'den *'yi seçin b.id = c.id üzerinde c birleştirme

Yerleşik optimize edici, gereksiz isteği tarayacak ve her şey yoluna girecek.

Ayrıca neyin daha iyi olduğuna kendisi karar verecek - var olmak mı yoksa katılmak mı ve çok daha fazlası. Ve her şey mümkün olduğu kadar optimum şekilde çalışacak.

Tek bir AMA var. Bir noktada optimizasyon aracı takılıp düşecek karmaşık sorgu ve geçer ve sonra büyük bir sorunla karşılaşırsınız. Ve bunu hemen alamayabilirsiniz, ancak masaların ağırlığı kritik kütleye ulaştığında.

İşte makalenin amacına geliyoruz. mevcut ve çok ağır operasyonlar var. Bu aslında ayrı bir alt sorgu her biri için sonuç satırları. Ve eğer yuvalama da varsa, o zaman genellikle ışıklar sönüyor demektir. 1, 10, 50 satır döndürüldüğünde her şey yoluna girecek. Farkı hissetmeyeceksiniz ve belki de katılım daha da yavaş olacaktır. Ancak 500 çekildiğinde sorunlar başlıyor. Bir istekte 500 alt sorgu bulunması ciddi bir durumdur.

Her ne kadar insan anlayışı açısından in ve asset daha iyi olsa da, 50'den fazla satır döndüren sorgular için zaman maliyeti açısından bunlar kabul edilemez.

Rezervasyon yaptırmak gerekiyor ki doğal olarak bir yerde azalırsa mutlaka bir yere varır. Evet, join daha fazla hafıza yoğundur, çünkü değer tablosunun tamamını aynı anda tutmak ve onunla çalışmak, her satır için alt sorguları çalıştırmaktan daha pahalıdır ve hafızayı hızla boşaltır. İsteğe özel olarak bakmanız ve fazladan belleğin zaman uğruna kullanılmasının kritik olup olmayacağını ölçmeniz gerekir.

Tam analojilerin örneklerini vereceğim. Genel olarak konuşursak, bir dizi birleştirmeye genişletilemeyecek kadar karmaşıklık derecesine sahip sorgularla henüz karşılaşmadım. Bir gün sürebilir ama her şey ortaya çıkabilir.

a.id'nin bulunduğu yerden * seçin (b'den kimliği seçin) a'nın bulunduğu yerden * seçin (b.id = a.id olan b'den ilk 1 1'i seçin) a.id = b'deki b birleşiminden * seçin. id a.id'nin olmadığı yerden *'yi seçin (b'den id seçin) a'nın bulunmadığı yerden *'yi seçin (b'den ilk 1 1'i seçin, burada b.id = a.id) a'nın sol birleşiminden *'yi seçin. id = b.id burada b.id boştur

Tekrar ediyorum - MSSQL iyileştiricisi bu örnekleri aşağıdakiler için optimize eder: maksimum performans ve asla bu kadar basit istekleri olan aptal insanlar olmayacak.

Şimdi bazı örneklerde donduğu için yeniden yazılması gereken gerçek bir sorgu örneğini ele alalım (yapı çok basitleştirildi ve kavramlar değiştirildi, veritabanı yapısının optimal olmamasından korkmaya gerek yok) ).

Ürünün, grubunun ve varsa ana grubun parametrelerine odaklanarak farklı hesaplardaki tüm yinelenen "ürünleri" çıkarmanız gerekir.

product s'den d.product_ID'yi seçin, TECH_GROUP sg sol M_PG_DEPENDENCY sd'ye katılın (sg.product_GROUP_ID = sd.M_PG_DEPENDENCY_CHILD_ID), TECH d, TECH_GROUP dg sol M_PG_DEPENDENCY dd'ye katılın (dg.product_GROUP_ID = dd .M_PG_DEPENDENCY_) CHILD_ID) burada s.product_GROUP_ID=sg ... IS_SECURE ve s.product_MULTISELECT=d.product_MULTISELECT ve dg.product_GROUP_IS_TMPL=0 ve ((sd.M_PG_DEPENDENCY_CHILD_ID boştur ve dd.M_PG_DEPENDENCY_CHILD_ID boştur) veya mevcut (product_GROUP sg1, product_GROUP dg1'den 1 seçin; burada sd.M_PG_DEPENDENCY _PARENT_ID = sg1.product_GROUP_ID ve dd .M_PG_DEPENDENCY_PARENT_ID = dg1.product_GROUP_ID ve sg1.product_GROUP_PERSPEC=dg1.product_GROUP_PERSPEC ve sg1.product_GROUP_NAME=dg1.product_GROUP_NAME ve))

Optimize edicinin pes ettiği durum budur. Ve her satır için veritabanını öldüren ağır bir var oluş yürütüldü.

product s'den d.product_ID'yi seçin s.product_TYPE=d.product_TYPE ve s.product_NAME=d.product_NAME üzerinde product d'ye katılın ve s.product_is_SECURE=d.product_is_secure ve s.product_multiselect=d.product_multiselect s.product_group_id= üzerinde product_group sg'ye katılın sg.product_GROUP_ID d.product_GROUP_ID=dg.product_GROUP_ID üzerinde product_GROUP dg'ye katılın ve sg.product_GROUP_NAME=dg.product_GROUP_NAME ve sg.product_GROUP_PERSPEC=dg.product_GROUP_PERSPEC kaldı sg.product_GROUP_ID üzerinde M_PG_DEPEND ENCY sd'ye katılın = sd.M _PG_DEPENDENCY_CHILD_ID, dg'de M_PG_DEPENDENCY dd'ye katıldı. product_GROUP_ID = dd.M_PG_DEPENDENCY_CHILD_ID kaldı, sgp'de RIM_GROUP sgp'ye katıldı.product_GROUP_ID = sd.M_PG_DEPENDENCY_PARENT_ID, dgp'de RIM_GROUP dgp'ye katıldı.product_GROUP_ID = dd.M_PG_DEPENDENCY_PARENT_ID ve sgp.PRODUC T_GROUP_NAME = dgp.product_GROUP_NAME ve isnull(sgp.product_GROUP_IS_TMPL, 0) = isnull( dgp. TECH_GROUP_IS_TMPL, 0) burada (sd.M_PG_DEPENDENCY_CHILD_ID boştur ve dd.M_PG_DEPENDENCY_CHILD_ID boş değildir) veya (sgp.product_GROUP_NAME boş değildir ve dgp.product_GROUP_NAME boş değildir) git

Bu dönüşümlerden sonra görünümün performansı, bulunan ürün sayısıyla birlikte katlanarak arttı. Daha doğrusu, arama süresi pratik olarak eşleşme sayısından bağımsız kaldı ve her zaman çok küçüktü. Olması gerektiği gibi.

Bu, MSSQL optimizasyon aracına güvenmenin ne kadar acımasız bir şaka yapabileceğinin açık bir örneğidir. Ona güvenmeyin, tembel olmayın, manuel olarak katılın, her seferinde belirli bir durumda neyin daha iyi olduğunu düşünün - mevcut, içinde veya katılın.

SQL dili yüklemi EXISTS mantıksal bir görevi gerçekleştirir. İÇİNDE SQL sorguları bu yüklem, formun ifadelerinde kullanılır

MEVCUT (TABLE_NAME'DEN * SEÇİN ...).

Bu ifade, sorgu koşulla eşleşen bir veya daha fazla satır bulduğunda true değerini döndürür, hiçbir satır bulunamadığında false değerini döndürür.

MEVCUT DEĞİL için durum tam tersidir. İfade

MEVCUT DEĞİL (TABLE_NAME'DEN * SEÇİN ...)

Sorguda hiçbir satır bulunmadığında true değerini, en az bir satır bulunduğunda false değerini döndürür.

SQL EXISTS yüklemi ile en basit sorgular

Örneklerde kütüphane veri tabanı ve onun “Kullanılan Kitap” (BOOKINUSE) ve “Kullanıcı” (USER) tablolarıyla çalışıyoruz. Şimdilik sadece “Kullanılan Kitap” tablosuna (BOOKINUSE) ihtiyacımız var.

YazarBaşlıkPubyearFatura_NoKullanıcı kimliği
TolstoySavaş ve Barış2005 28 65
ÇehovKiraz Bahçesi2000 17 31
ÇehovSeçilmiş hikayeler2011 19 120
ÇehovKiraz Bahçesi1991 5 65
Ilf ve PetrovOn iki Sandalye1985 3 31
MayakovskiŞiirler1983 2 120
Yaban havucuDoktor Jivago2006 69 120
TolstoyPazar2006 77 47
TolstoyAnna Karenina1989 7 205
PuşkinKaptanın kızı2004 25 47
GogolOynatmalar2007 81 47
ÇehovSeçilmiş hikayeler1987 4 205
Yaban havucuFavoriler2000 137 18

Örnek 1. Tolstoy'un kitapları verilen ve ayrıca Çehov'un kitapları verilen kullanıcıların kimliklerini belirleyin. Dış sorgu, Tolstoy'un kitapları verilen kullanıcılar hakkındaki verileri seçer ve EXISTS yüklemi, iç sorguda işaretlenen ek bir koşulu belirtir: Çehov'un kitapları verilen kullanıcılar. Dahili istekteki ek bir koşul, harici ve dahili isteklerdeki kullanıcı kimliklerinin eşleşmesidir: User_ID=tols_user.user_id. Talep şu şekilde olacaktır:

Bu sorgu aşağıdaki sonucu döndürecektir:

EXISTS ve IN yüklemleri arasındaki farklar

EXISTS yüklemi ile yapılan sorgulara ilk bakışta aynı olduğu izlenimini edinebilirsiniz. yüklem IN. Bu yanlış. Her ne kadar çok benzer olsalar da. IN yüklemi, bağımsız değişkeninde belirtilen aralıktaki değerleri arar ve bu tür değerler varsa bu aralığa karşılık gelen tüm satırlar seçilir. EXISTS yükleminin sonucu, argümanda belirtilenlere karşılık gelen herhangi bir değerin olup olmadığı sorusuna "evet" veya "hayır" yanıtıdır. Ayrıca IN yükleminin önüne, aralıktaki değerlerle eşleşen satırların aranacağı sütunun adı gelir. EXISTS yüklemi ile IN yüklemi arasındaki farkı ve IN yüklemi kullanılarak çözülen sorunu gösteren bir örneğe bakalım.

Örnek 4. 31 ID'li kullanıcıya kitapları verilen yazarlar tarafından kitap verilen kullanıcıların kimliklerini belirleyin. Talep şu şekilde olacaktır:

Kullanıcı kimliği
120
65
205

Dahili bir sorgu (IN'den sonra) yazarları seçer: Çehov; Ilf ve Petrov. Harici sorgu, bu yazarların kitaplarını verdiği tüm kullanıcıları seçer. EXISTS yükleminden farklı olarak IN yükleminden önce sütunun adının (bu durumda Yazar) geldiğini görüyoruz.

EXISTS yüklemi ve ek koşulları içeren sorgular

Sorgudaki EXISTS yüklemine ek olarak en az bir ek koşul uygularsanız (örneğin, kullanılarak belirtilen), toplama işlevleri, bu tür sorgular basit veri analizine hizmet edebilir. Bunu aşağıdaki örnekle gösterelim.

Örnek 5. Pasternak'a ait en az bir kitap dağıtılan ve 2'den fazla kitap dağıtılan kullanıcıların kimliklerini belirleyin. İlk koşulun EXISTS yüklemi tarafından iç içe bir sorgu ile belirtildiği ve HAVING operatörü ile ikinci koşulun her zaman iç içe sorgudan sonra gelmesi gerektiği aşağıdaki sorguyu yazıyoruz:

Talebin sonucu:

Kullanıcı kimliği
120

BOOKINUSE tablosundan da görüleceği üzere Pasternak’ın kitabı da kullanıcıya ID 18 ile verilmiş ancak kendisine sadece bir kitap verilmiş ve örnekte yer almamış. COUNT fonksiyonunu benzer bir sorguya tekrar uygularsanız, ancak bu sefer seçilen satırları saymak için (bunu kendiniz uygulayın), Pasternak'ın kitaplarını okuyan kaç kullanıcının aynı zamanda başka yazarların kitaplarını da okuduğu hakkında bilgi alabilirsiniz. Bu zaten veri analizi alanından.

EXISTS içeren sorgular iki tabloyu temel alır

EXISTS yüklemi ile yapılan sorgular birden fazla tablodan veri alabilir. Birçok problem aynı sonuçla çözülebilir. KATILIN operatörü, ancak bazı durumlarda EXISTS kullanmak daha az hantal bir sorgu oluşturmanıza olanak tanır. Ortaya çıkan tablonun yalnızca bir tablodan sütunlar içereceği durumlarda EXISTS kullanılması tercih edilir.

Aşağıdaki örnekte aynı veritabanından BOOKINUSE tablosuna ek olarak bir USER tablosuna da ihtiyacınız olacak.

Sorgunun sonucu aşağıdaki tablo olacaktır:

Yazar
Çehov
Mayakovski
Yaban havucu

JOIN operatörünün kullanımında olduğu gibi birden fazla tablonun olduğu durumlarda tablo takma adlarını kullanarak tabloları birbirine bağlayan anahtarların değerlerinin eşleşip eşleşmediğini kontrol etmelisiniz. Örneğimizde tablo takma adları bk ve us, tabloları birbirine bağlayan anahtar ise User_ID'dir.

İkiden fazla tablonun birleşiminde EXISTS yüklemi

Şimdi, ortaya çıkan tablonun yalnızca bir tablodan sütunlar içereceği durumlarda EXISTS kullanmanın neden tercih edildiğini daha ayrıntılı olarak göreceğiz.

"Emlak" veritabanıyla çalışıyoruz. Anlaşma tablosu anlaşmalarla ilgili verileri içerir. Görevlerimiz için, bu tabloda işlem türüne (satış veya kiralama) ilişkin verileri içeren Tür sütunu önemli olacaktır. Nesne tablosu nesnelerle ilgili verileri içerir. Bu tabloda, Boolean formatında bir sundurma veya balkonun varlığına ilişkin verileri içeren Odalar (oda sayısı) ve LogBalc sütunlarının değerlerine ihtiyacımız olacak: 1 (evet) veya 0 (hayır). Müşteri, Yönetici ve Sahip tabloları sırasıyla müşteriler, şirket yöneticileri ve mülk sahipleriyle ilgili verileri içerir. Bu tablolarda FName ve LName sırasıyla ad ve soyadıdır.

Örnek 7. Sundurması veya balkonu olmayan mülkleri satın alan veya kiralayan müşterileri belirleyin. EXISTS yükleminin iki tabloyu birleştirme sonucuna erişimi belirttiği aşağıdaki sorguyu yazıyoruz:

Sütunlar, yıldız işareti operatörü kullanılarak İstemci tablosundan seçildiğinden, EXISTS yüklemi tarafından belirtilen koşulla eşleşen istemci sayısı kadar satıra sahip olacak şekilde bu tablonun tüm sütunları görüntülenecektir. Alt sorgu tarafından birleşime erişilen tablolardan herhangi bir sütunun çıktısını almamıza gerek yoktur. Bu nedenle makine zamanından tasarruf etmek için yalnızca bir sütun alınır. Bunun için SELECT sözcüğünden sonra bir birim yazılır. Aşağıdaki örneklerdeki sorgularda da aynı teknik kullanılmıştır.

EXISTS yüklemini kendiniz içeren bir SQL sorgusu yazın ve ardından çözüme bakın

EXISTS yüklemi ile birlikte SQL sorguları yazmaya devam ediyoruz

Örnek 9. Kiralanan nesnelerin sahiplerini belirleyin. EXISTS yükleminin aynı zamanda iki tabloyu birleştirme sonucuna erişimi de belirttiği aşağıdaki sorguyu yazıyoruz:

Önceki örnekte olduğu gibi, tablodaki harici sorgu tarafından erişilen tüm alanlar döndürülecektir.

Örnek 10. Mülkleri yönetici Savelyev tarafından idare edilen sahiplerin sayısını belirleyin. Dış sorgunun üç tablonun birleşimine eriştiği ve EXISTS yükleminin yalnızca bir tabloya erişimi belirttiği bir sorgu yazıyoruz:

Tüm sorgular mevcut bir veritabanına göre kontrol edilir. Başarılı kullanım!

İlişkisel Veritabanları ve SQL Dili

Novosibirsk Devlet Ekonomi ve Yönetim Akademisi

DİSİPLİN LABORATUVAR UYGULAMASI

"VERİ TABANI"

7 numaralı laboratuvar çalışması

"Temellerin dili SQL verileri: veri işleme komutları»

NOVOSİBİRSK 2000

SQL, Yapılandırılmış Sorgu Dili'nin kısaltmasıdır. Dilin adından da anlaşılabileceği gibi asıl amacı veri tabanından bilgi elde etmek için sorgular üretmektir. Veri alma komutları, SQL dilinin ayrılmaz bir parçası olan veri işleme dili DML'nin temelini oluşturur. Ancak DML, bir veritabanından veri almak için kullanılan komutlardan daha fazlasını içerir. Ayrıca veri değişikliği, veri yönetimi ve diğerleri için komutlar da vardır.

Laboratuvar çalışması DML dilinin temel araçlarını inceliyor. Devam etmekte laboratuvar işi SQL2 standardına bağlı kalacağız.

SQL'in geniş bir dil olması nedeniyle sadece temel komutları ele alacağız. Sonraki laboratuvarlarda çeşitli spesifik SQL araçları ele alınacaktır.

Laboratuvar çalışmasını gerçekleştirmek için ilişkisel veri modelinin temelleri, ilişkisel cebir ve ilişkisel hesabın temelleri ve MS SQL Server DBMS ile çalışmanın ilkeleri hakkında bilgi gereklidir.

Laboratuvar çalışmasının tamamlanmasının bir sonucu olarak, SQL dil komutlarını kullanarak verileri işleme yöntemlerinde uzmanlaşacak, MS SQL Server DBMS'de uygulanan dilin lehçesini göz önünde bulunduracaksınız.

GİRİİŞ

SQL, hem sorgu oluşturmak hem de veritabanını güncellemek için çok çeşitli veri işleme yetenekleri içerir. Bu yetenekler, ilişkisel modelin gereksinimleriyle tutarlı olan fiziksel yapısına değil, yalnızca veritabanının mantıksal yapısına dayanır.

SQL sözdiziminin orijinal yapısı Codd'un ilişkisel hesabına dayanıyordu (veya en azından öyle görünüyordu). İlişkisel cebirde desteklenen tek işlem birleştirme işlemiydi.

Önceki standartta geliştirilen ilişkisel analiz benzeri sözdizimine ek olarak SQL2, birleştirme, kesişme, fark ve birleştirme işlemlerini doğrudan uygular. Seçim, proje ve ürün işlemleri neredeyse doğrudan desteklenirken (ve desteklenmeye de devam ediyor), bölme ve atama işlemleri ise daha hantal bir biçimde destekleniyor.

Öncelikle SQL sorgu dilini, ardından veri girişi ve değiştirme işlemlerini anlatacağız. Veri değiştirme işlemleri, yapıları bir dereceye kadar sorgulama dilinin yapısına bağlı olduğundan, son olarak açıklanacaktır.

Basit sorgular

Bizim için basit istek veritabanında yalnızca bir tabloya erişen bir sorgu olacaktır. Basit sorgular SQL'in temel yapısını göstermemize yardımcı olacaktır.

Basit istek. Yalnızca bir veritabanı tablosuna erişen bir sorgu.

Rica etmek: Kimler sıvacı olarak çalışır?

WHERE SKILL_TYPE = "Sıvacı"

Sonuç:

G.Rickover

Bu sorgu en yaygın üçünü göstermektedir cümleler SQL: SEÇ, KİMDEN ve NEREDEN. Örneğimizde bunları farklı satırlara yerleştirmiş olsak da hepsi aynı satırda görünebilir. Ayrıca farklı girintilere de sahip olabilirler ve ifadelerin içindeki kelimeler isteğe bağlı sayıda boşlukla ayrılabilir. Her cümlenin özelliklerine bakalım.

Seçme. SELECT yan tümcesi, sonuç tablosunda görünmesi gereken sütunları listeler. Bunlar her zaman bazı ilişkisel tabloların sütunlarıdır. Örneğimizde ortaya çıkan tablo bir sütundan (NAME) oluşur, ancak genel olarak birden fazla sütun içerebilir; hesaplanan değerleri veya sabitleri de içerebilir. Bu seçeneklerin her birine örnekler vereceğiz. Ortaya çıkan tablonun birden fazla sütun içermesi gerekiyorsa, gerekli tüm sütunlar sonra listelenir. komutları seç virgüllerle ayrılmış. Örneğin, SELECT WORKER_ID, NAME ifadesi, WORKER_ID ve NAME sütunlarından oluşan bir tabloyla sonuçlanacaktır.

SELECT cümlesi. Ortaya çıkan tablonun sütunlarını belirtir.

İtibaren. FROM yan tümcesi, sorgu tarafından erişilen bir veya daha fazla tabloyu belirtir. SELECT ve WHERE yan tümcelerinde listelenen tüm sütunların, FROM komutunda listelenen tablolardan birinde mevcut olması gerekir. SQL2'de bu tablolar doğrudan şemada temel tablolar veya veri görünümleri olarak tanımlanabilir veya kendileri SQL sorgularından kaynaklanan adsız tablolar olabilir. İkinci durumda, istek açıkça FROM komutunda verilir.

FROM ifadesi. Sorgu tarafından erişilen mevcut tabloları belirtir.

Nerede. WHERE cümlesi bir koşul içerir. tablo(lar)ın satırları buna göre seçilir. Örneğimizde koşul, SQL'deki metin sabitlerinde her zaman yapıldığı gibi, SKILL_TYPE sütununun kesme işaretleri içine alınmış "Plasterer" sabitini içermesi gerektiğidir. WHERE yan tümcesi en değişken SQL komutudur; birçok farklı durumu içerebilir. Tartışmamızın büyük bir kısmı WHERE komutunda izin verilen çeşitli yapıları göstermeye ayrılacaktır.

WHERE cümlesi. Belirtilen tablolardan hangi satırların seçildiğine bağlı olarak koşulu belirtir.

Yukarıdaki SQL sorgusu sistem tarafından şu sırayla işlenir: FROM, WHERE, SELECT. Yani FROM komutunda belirtilen tablonun satırları işlenmek üzere çalışma alanına yerleştirilir. WHERE cümlesi daha sonra her satıra sırayla uygulanır. WHERE koşulunu karşılamayan tüm satırlar değerlendirme dışı bırakılır. Daha sonra WHERE koşulunu karşılayan satırlar SELECT ifadesi tarafından işlenir. Örneğimizde bu satırların her birinden NAME seçilir ve seçilen tüm değerler sorgu sonuçları olarak çıkarılır.

Rica etmek: Ofis binaları hakkında tüm bilgileri sağlayın.

NEREDE TÜR = "Ofis"

Sonuç:

BLDG IDADRESTÜRÜQLTY DÜZEYDURUM

312 Elm St., 123 Ofis 2 2

210 Berezovaya caddesi. 1011 Ofis Z 1

111 Osinovaya caddesi. 1213 Ofis 4 1

SELECT komutundaki yıldız işareti (*), "satırın tamamı" anlamına gelir. Bu sık sık kullanacağımız kullanışlı bir kısaltmadır.

Rica etmek: Her elektrikçinin haftalık maaşı nedir?

İSİM SEÇİN, "Haftalık maaş = ", 40 * HRLY_RATE

WHERE SKILL_TYPE = "Elektrikçi"

Sonuç:

M. Faraday Haftalık maaş = 500.00

H.Columbus Haftalık maaş = 620.00

Bu sorgu, hem karakter sabitlerinin (örneğimizde "Haftalık maaş = ") hem de SELECT komutundaki hesaplamaların kullanımını gösterir. SELECT deyimi içinde, standart aritmetik operatörlerin yanı sıra sayısal sütunları ve sayısal sabitleri kullanan hesaplamalar gerçekleştirebilirsiniz ( +, -, *, /), parantez kullanılarak gerektiği şekilde gruplandırılmıştır. Ayrıca yeni bir tane ekledik SİPARİŞ komutu BY, sorgu sonucunu belirtilen sütuna göre artan alfasayısal düzende sıralar. Sonuçları azalan şekilde sıralamak istiyorsanız komuta DESC eklemeniz gerekir. ORDER BY yan tümcesi, sonuçları birden çok sütuna göre sıralayabilir; bunların bazıları artan sırada, diğerleri azalan sıradadır. Sıralamanın birincil anahtar sütunu ilk olarak listelenir.

Karakter sabiti. Harflerden, rakamlardan ve “özel” karakterlerden oluşan bir sabit.

Rica etmek: Kimin saatlik ücreti 10 ile 12 dolar arasında?

WHERE HRLY_RATE > = 10 VE HRLY_RATE< - 12

Sonuç:

İŞÇİ KİMLİĞİİSİM HRLY_RATE SKILL_TYPE SUPV_ID

Bu sorgu, WHERE ifadesinin bazı ek özelliklerini gösterir: karşılaştırma operatörleri ve Boolean AND operatörü. Altı karşılaştırma operatörü (=,<>(eşit değil),<, >, <=, >=). Boolean operatörleri AND, OR ve NOT, bileşik koşullar oluşturmak veya bir koşulu olumsuzlamak için kullanılabilir. Parantezler, programlama dillerinde yaygın olduğu gibi koşulları gruplamak için kullanılabilir.

Karşılaştırma operatörleri =,<>, <, >, <=, >=.

Boole işlemleri VE (VE), VEYA (VEYA) ve DEĞİL (HE) .

Bu sorguyu formüle etmek için BETWEEN (arasında) operatörünü de kullanabilirsiniz:

HRLY_RATE'IN 10 İLE 12 ARASI NEREDE

BETWEEN, bir miktarı, birincisi ikincisinden küçük olan diğer iki büyüklükle karşılaştırmak için kullanılabilir; eğer karşılaştırılan miktar bu büyüklüklerin her birine veya aradaki herhangi bir değere eşitse.

Talep: Sıvacıların, çatı ustalarının ve elektrikçilerin listesini yapın.

WHERE SKILL_TYPE IN ("Sıvacı", "Çatı Ustası", "Elektrikçi")

Sonuç:

İŞÇİ_ID ADI HRLY_RATE SKILL_TYPE SUPV_ID

1412 K.Nemo 13.75 Sıvacı 1520

2920 R. Garrett 10.00 Çatı Ustası 2920

1520 G. Rickover 11.75 Sıvacı 1520

Bu sorgu IN (B) karşılaştırma operatörünün kullanımını açıklamaktadır. Satırın uzmanlık türü parantez içinde belirtilen kümenin içinde yer alıyorsa, yani uzmanlık türü sıvacı, çatı ustası veya elektrikçi ise WHERE koşulu doğru kabul edilir. IN operatörünü alt sorgularda tekrar göreceğiz.

Uzmanlık alanımızın yazılışını tam olarak hatırlayamadığımızı varsayalım: “elektrikçi” ya da “elektronik mühendisi” ya da başka bir şey. Tanımlanmamış karakter dizelerinin yerine geçen joker karakterler, bir sorguda hatalı yazımların bulunmasını kolaylaştırır.

Desen sembolleri. Tanımlanmamış karakter dizelerinin yerini alan karakterler.

Rica etmek: Uzmanlık türü “Elek” ile başlayan çalışanları listeleyiniz.

WHERE SKILL_TYPE LIKE ("Seçim Yüzdesi")

Sonuç:

İŞÇİ KİMLİĞİ ADI HRLY_RATE SKILL_TYPE SUPV_ID

1235 M. Faraday 12.50 Elektrikçi 1311

1311 H. Columbus 15.50 Elektrik 1311

SQL'de iki joker karakter bulunur: % (yüzde) ve _ (alt çizgi). Alt çizgi tam olarak bir tanımsız karakterin yerine geçer. Yüzde, sıfırdan başlayarak isteğe bağlı sayıda karakterin yerini alır. Joker karakterler kullanıldığında, karakter değişkenlerini sabitlerle karşılaştırmak için bir LIKE operatörü gerekir. Diğer örnekler:

"__Columbus" GİBİ İSİM

"__K%" GİBİ İSİM

NAME, ardından "Columbus" gelen iki karakterden oluşuyorsa ilk örnekteki koşul doğrudur. WORKER tablosunda tüm adlar ilk harf ve nokta ile başlar. Böylece bu koşulu kullanarak biz. "Columbus" soyadına sahip tüm çalışanları bulalım. İkinci örneğin koşulu, soyadı “K” harfiyle başlayan tüm çalışanları bulmamızı sağlıyor.

Rica etmek:Önümüzdeki iki hafta içinde başlayacak tüm işleri bulun.

CURRENT_DATE VE START_DATE ARASI NEREDE

Sonuç:(Geçerli tarihin GÜNCEL TARİH = 10.10 olduğunu varsayalım)

WORKER_ID BLDG_ID START_DATE NUM_DAYS

1235 312 10.10 5

1235 515 17.10 22

3231 111 10.10 8

1412 435 15.10 15

3231 312 24.10 20

1311 460 23.10 24

Bu sorgu, BETWEEN operatörünün tarih ve aralık değerleriyle kullanımını gösterir. CURRENT_DATE her zaman bugünün tarihini döndüren bir işlevdir. İfade

CURRENT_DATE + INTERVAL "14" GÜN

geçerli tarihe iki haftalık bir süre ekler. Bu nedenle, START_DATE sütununun değeri 10/10 ile 10/24 arasında ise ATAMA seçilir (bugün 10/10 olduğu varsayılarak). Buradan tarih alanlarına aralık değerleri ekleyebildiğimizi görebiliriz. Üstelik aralıkların değerlerini tam sayı değerleriyle çarpabiliriz. Örneğin, belirli sayıda hafta içinde hangi sayının olacağını (NUM_WEEKS değişkeniyle gösterilir) bulmak istediğimizi varsayalım. Bunu şu şekilde yapabiliriz:

CURRENT_DATE + INTERVAL "7" GÜN * NUM_WEEKS

2. Çok tablolu sorgular

Veri öğelerini tek bir tablonun sınırları boyunca ilişkilendirme yeteneği, herhangi bir veritabanı dili için önemlidir. İlişkisel cebirde bu fonksiyon birleştirme işlemi ile gerçekleştirilir. Her ne kadar SQL'in çoğu doğrudan ilişkisel hesaba dayalı olsa da, SQL farklı tablolardan gelen verileri ilişkisel cebirin birleştirme işlemine benzer şekilde bağlar. Şimdi bunun nasıl yapıldığını göstereceğiz. Talebi düşünün:

Rica etmek:

Cevap için gereken veriler iki tabloda yer almaktadır: İŞÇİ ve ATAMA. SQL çözümü, her iki tablonun da FROM komutunda listelenmesini ve özel bir WHERE yan tümcesi türünün belirtilmesini gerektirir:

SKILL_TYPE SEÇİN

İŞÇİDEN, GÖREV

NEREDE WORKER.WORKER_ID = ATAMA.WORKER_ID

VE BLDG_ID = 435

Burada neler oluyor? Sistemin bu isteği nasıl işlediğine ilişkin iki aşamayı dikkate almalıyız.

1. Her zamanki gibi ilk önce FROM cümleciği işlenir. Ancak bu durumda komut iki tablo belirttiğinden sistem bu tabloların satırlarının Kartezyen çarpımını oluşturur. Bu, her iki tablonun sütunlarından oluşan (mantıksal olarak) büyük bir tablonun oluşturulduğu ve bir tablonun her satırının diğer tablonun her satırıyla eşlendiği anlamına gelir. Örneğimizde WORKER tablosunun beş sütunu ve ASSIGNMENT tablosunun dört sütunu olduğundan, FROM komutuyla üretilen Kartezyen çarpımının dokuz sütunu olacaktır. Kartezyen çarpımının toplam satır sayısı m * n'ye eşittir; burada m, WORKER tablosunun satır sayısıdır; ve n, ATAMA tablosundaki satır sayısıdır. WORKER tablosunda 7 satır ve ATAMA tablosunda 19 satır olduğundan Kartezyen çarpımı 7x19 veya 133 satır içerecektir. FROM komutu ikiden fazla tabloyu listeliyorsa, komutta belirtilen tüm tabloların Kartezyen çarpımı oluşturulur.

Kartezyen ürün. Bir tablonun her satırının birleştirilmesi sonucu her biri başka bir tablodan bir satır.

2. Devasa ilişkisel tabloyu oluşturduktan sonra sistem daha önce olduğu gibi WHERE komutunu kullanır. FROM komutu tarafından oluşturulan tablonun her satırı. WHERE koşulunun sağlanıp sağlanmadığı kontrol edilir. Koşulu karşılamayan satırlar değerlendirmeye alınmaz. SELECT yan tümcesi daha sonra kalan satırlara uygulanır.

Sorgumuzdaki WHERE yan tümcesi iki koşul içerir:

1. İŞÇİ. WORKER_ID = ATAMA.WORKER_ID

2.BLDG_ID = 435

Bu koşullardan ilki birleştirme koşuludur. Hem WORKER hem de ATAMA tabloları WORKER_ID adında bir sütun içerdiğinden Kartezyen çarpımının bu adda iki sütun içereceğini unutmayın. Aralarında ayrım yapmak için sütun adının önüne kaynak tablonun adını noktayla ayırarak koyarız.

İlk koşul, seçilen herhangi bir satırda, WORKER tablosundaki WORKER_ID sütununun değerinin ATAMA tablosundaki WORKER_ID sütununun değeriyle eşleşmesi gerektiği anlamına gelir. Gerçekte WORKER_ID'ye göre iki tabloyu birleştiriyoruz. Bu iki sütunun değerlerinin eşit olmadığı tüm satırlar ürün tablosunun dışında bırakılır. İlişkisel cebirin doğal birleştirme işlemini gerçekleştirirken de tamamen aynı şey olur. (Ancak doğal birleştirmeden hala bazı farklar vardır: SQL, fazladan WORKER_ID sütununu otomatik olarak kaldırmaz). Bu iki tablonun BLDG_ID = 435 ek koşuluyla tam birleşimi Şekil 2'de gösterilmektedir. 1. SELECT komutunun kullanılması sonuçta aşağıdaki sorgu sonucunu verecektir:

BECERİ TÜRÜ

Sıvacı

Çatı ustası

Elektrikçi

Pirinç. 1. WORKER ve ASSIGNMENT tablolarına katılma

Şimdi SQL'de bir tablonun kendisine nasıl birleştirileceğini göstereceğiz.

Rica etmek: Yöneticilerinin adlarını belirterek çalışanları listeleyin.

A.WORKER_NAME, B.WORKER_NAME SEÇİN

İŞÇİ A'DAN, İŞÇİ B'DEN

NEREDE B.WORKER_ID = A.SUPV_ID

Bu örnekteki FROM yan tümcesi, WORKER tablosunun iki "kopyasını" oluşturarak onlara A ve B takma adlarını verir. Takma ad, tabloya verilen alternatif bir addır. Daha sonra WORKER tablosunun A ve B kopyaları, B'deki WORKER_ID ve A'daki SUPV_ID'nin eşitlik durumuna göre WHERE komutuyla birleştirilir. Böylece A'dan gelen her satır, A satırının yöneticisi hakkında bilgi içeren satır B'ye birleştirilir. (İncir. 2).

Pirinç. 2. WORKER tablosunun iki kopyasının birleştirilmesi

Her satırdan iki çalışan adı seçerek gerekli listeyi elde ederiz:

A.NAMEB.NAME

M. Faraday H. Columbus

K.Nemo G.Rickover R.Garrett R.Garrett

P. Mason P. Mason G. Rickover G. Rickover H. Columbus H. Columbus J. Avukat P. Mason

Takma ad. Tabloya verilen alternatif bir ad.

A.WORKER_NAME çalışanı, B.WORKER_NAME ise yöneticiyi temsil eder. Lütfen bazı çalışanların kendi yöneticileri olduğunu ve bunun da satırlarındaki WORKER_ID - SUPV_ID eşitliğinden kaynaklandığını unutmayın.

SQL'de aynı anda ikiden fazla tabloyu bağlayabilirsiniz:

Rica etmek

WORKER_NAME'İ SEÇİN

İŞÇİDEN, GÖREVDEN, BİNADAN

NEREDE WORKER.WORKER_ID = ASSIGNMENT.WORKER_ID VE ASSIGNMENT.BLDG_ID = BUILDING.BLDG_ID VE

TİP = "Ofis"

Sonuç:

M. Faraday

G.Rickover

J. Avukat

Bir sütun adı (örneğin, WORKER_ID veya BLDG_ID) birden fazla tabloda görünüyorsa, belirsizliği önlemek için sütun adının başına orijinal tablonun adını eklememiz gerektiğini unutmayın. Ancak, örneğimizdeki TYPE gibi sütun adı yalnızca bir tabloda geçiyorsa, o zaman belirsizlik olmaz, dolayısıyla tablo adının belirtilmesine gerek yoktur.

Bu sorgudaki SQL komutları, üç ilişkisel veritabanı tablosundan bir tablo oluşturur. İlk iki tablo WORKER_ID ile birleştirilir, ardından üçüncü tablo BLDG_ID ile sonuç tablosuna birleştirilir. Durum

TİP = "Ofis"

WHERE yan tümcesi, ofis binaları dışındaki tüm satırların hariç tutulmasına neden olur. Bu, talebin gereksinimlerini karşılar.

3. Alt Sorgular

Alt sorgu. Sorgu içinde sorgu

Bir sorgunun WHERE yan tümcesine bir alt sorgu yerleştirilebilir, böylece WHERE yan tümcesinin yetenekleri genişletilebilir. Bir örneğe bakalım.

Rica etmek: 435 nolu binada görevlendirilen işçilerin uzmanlıkları nelerdir?

SKTLL_TYPE SEÇİN

WORKER_ID'NİN BULUNDUĞU İŞÇİDEN

(WORKER_ID'Yİ SEÇİN

NEREDE BLDG_ID = 435)

Bu örnekte alt sorgu

(WORKER_ID'Yİ SEÇİN

NEREDE BLDG_ID = 435)

Alt sorgu içeren sorguya denir harici istek veya ana istek. Alt sorgu, aşağıdaki çalışan kimlikleri kümesinin oluşturulmasıyla sonuçlanır:

İŞÇİ KİMLİĞİ

Harici istek. Tüm alt sorguları içeren ana sorgu.

Bu kimlik kümesi daha sonra dış sorgudaki bir alt sorgunun yerini alır. Bu noktadan itibaren dış sorgu, alt sorgu tarafından oluşturulan küme kullanılarak yürütülür. Dış sorgu, WORKER tablosunun her satırını WHERE yan tümcesine göre işler. Bir satırın WORKER_ID'si alt sorgu tarafından oluşturulan (IN) kümesinde yer alıyorsa, satırın SKILL_TYPE'si seçilir ve sonuç tablosunda görüntülenir:

BECERİ TÜRÜ

Sıvacı

Çatı ustası

Elektrikçi

Alt sorgunun SELECT yan tümcesinin WORKER_ID'yi ve yalnızca WORKER_ID'yi içermesi çok önemlidir. Aksi takdirde, dış sorgunun WHERE yan tümcesinin, yani WORKER_ID'nin çalışan kimlikleri kümesinde olduğu anlamına gelmesinin hiçbir anlamı olmayacaktır.

Bir alt sorgunun, ana sorgu tarafından en az bir satır dikkate alınmadan önce mantıksal olarak yürütülebileceğini unutmayın. Bir bakıma alt sorgu ana sorgudan bağımsızdır. Tam sorgu olarak çalıştırılabilir. Böyle bir alt sorgunun ana sorguyla ilişkisi olmadığını söylüyoruz. Birazdan göreceğimiz gibi, alt sorgular ilişkilendirilebilir.

İlişkisiz alt sorgu. Değeri herhangi bir dış sorgudan bağımsız olan bir alt sorgu.

Aşağıda bir alt sorgu içindeki bir alt sorgu örneği verilmiştir.

Rica etmek: Ofis binalarında görevlendirilen çalışanları listeleyiniz.

Yine bağlantıyı incelediğimiz sorguya bakıyoruz.

WORKER_MAME'I SEÇİN

WORKER_ID NEREDE

(WORKER_ID'Yİ SEÇİN

BLDG_ID NEREDE

NEREDE TÜR = "Ofis"))

Sonuç:

M. Faraday

G.Rickover

J. Avukat

Her alt sorgu yalnızca bir tabloyu işlediğinden, herhangi bir belirsizlik ortaya çıkmayacağından, sütun adlarının önüne hiçbir yerde tablo adları koymamıza gerek olmadığını unutmayın.

Sorgu yürütme içten dışa sırayla gerçekleşir. Yani, önce en içteki sorgu (veya "en alttaki") yürütülür, ardından onu içeren alt sorgu yürütülür ve ardından dış sorgu yürütülür.

İlişkili Alt Sorgular. Yukarıda tartışılan alt sorguların tümü, kullanıldıkları ana sorgulardan bağımsızdı. Bağımsız derken, alt sorguların tam sorgular halinde kendi başlarına yürütülebileceğini kastediyoruz. Şimdi, yürütme sonuçları ana sorgu tarafından dikkate alınan satıra bağlı olabilen bir alt sorgu sınıfını ele almaya geçiyoruz. Bu tür alt sorgulara ilişkili alt sorgular denir.

İlişkili alt sorgu. Sonucu ana sorgu tarafından dikkate alınan satıra bağlı olan bir alt sorgu.

Rica etmek: Saat ücreti yöneticilerinin saat ücretinden yüksek olan çalışanları listeleyiniz.

WORKER_NAME'İ SEÇİN

NEREDE A.HRLY_RATE >

(B.HRLY_RATE SEÇİN

NEREDE B.WORKER_ID = A.SUPV_ID)

Sonuç:

Bu isteği yürütmenin mantıksal adımları şunlardır:

1. Sistem İŞÇİ tablosunun iki kopyasını oluşturur: A kopyası ve B kopyası. Tanımlama şeklimize göre A çalışanı, B yöneticiyi ifade eder.

2. Sistem daha sonra her A satırını dikkate alır. WHERE koşulunu karşılıyorsa belirli bir satır seçilir. Bu koşul, bir satırın HRLY_RATE değeri alt sorgu tarafından oluşturulan HRLY_RATE değerinden büyükse seçileceği anlamına gelir.

3. Alt sorgu, WORKER_ID'si A satırının SUPV_ID'sine eşit olan B satırından HRLY_RATE değerini seçer. şu an ana istek tarafından dikkate alınır. Bu, yöneticinin HRLY_RATE oranıdır.

A.HRLY_RATE yalnızca bir değerle karşılaştırılabileceği için alt sorgunun yalnızca bir değer döndürmesi gerektiğini unutmayın. Bu değer hangi A satırının dikkate alındığına bağlı olarak değişir. Böylece alt sorgu ana sorguyla ilişkilendirilir. Daha sonra yerleşik işlevleri incelediğimizde ilişkili alt sorgulara ilişkin daha fazla örnek göreceğiz.

EXISTS ve NOT EXISTS operatörleri

Belirli bir binada çalışmak üzere görevlendirilmeyen işçileri belirlemek istediğimizi varsayalım. Görünüşte böyle bir talebin, talebin olumlu versiyonunun reddedilmesiyle kolaylıkla karşılanabileceği görülmektedir. Örneğin, BLDG_ID 435'e sahip bir binayla ilgilendiğimizi varsayalım. İsteği göz önünde bulundurun:

WORKER_ID'Yİ SEÇİN

BLDG_ID 435 DEĞİL NEREDE

Ne yazık ki bu, çözümün yanlış bir formülasyonudur. Talep bize yalnızca diğer binalarda çalışan işçilerin kimliklerini verecek. Açıkçası bunlardan bazıları 435 numaralı binaya da atanabilir.

Doğru şekilde formüle edilmiş bir çözüm NOT EXISTS operatörünü kullanır:

WORKER_ID'Yİ SEÇİN

OLMAYAN YERDE

NEREDE ATAMA.WORKER_ID = WORKER.WORKER_ID VE

Sonuç:

İŞÇİ_ID

EXISTS ve NOT EXISTS operatörleri her zaman alt sorgudan önce yerleştirilir. EXISTS, alt sorgu tarafından oluşturulan küme boş değilse doğru olarak değerlendirilir. Alt sorgu tarafından oluşturulan küme boşsa EXISTS "false" değerini alır. NOT EXISTS operatörü elbette tam tersi şekilde çalışır. Alt sorgunun sonucu boşsa doğru, değilse yanlıştır.

MEVCUT operatör. Sonuç kümesi boş değilse true değerini döndürür.

MEVCUT DEĞİL operatörü. Sonuç kümesi boşsa true değerini döndürür.

Bu örnekte NOT EXISTS operatörünü kullandık. Alt sorgu, WORKER_ID'nin ana sorgu tarafından dikkate alınan satırla aynı değere sahip olduğu ve BLDG_ID'nin 435'e eşit olduğu ASSIGNMENT tablosunun tüm satırlarını seçer. Bu küme boşsa, ana sorgu tarafından dikkate alınan çalışan satırı: seçildi, çünkü bu şu anlama gelir: Bu çalışan 435 numaralı binada çalışmıyor.

Sunduğumuz çözümde ilişkili bir alt sorgu kullandık. NOT EXISTS yerine IN operatörünü kullanırsak ilişkisiz bir alt sorguyla idare edebiliriz:

WORKER_ID'Yİ SEÇİN

İŞÇİ_ID'NİN YER ALMADIĞI YER

(WORKER_ID'Yİ SEÇİN

NEREDE BLDG_ID = 435)

Bu çözüm, NOT EXISTS operatörüyle yapılan çözümden daha basittir. Doğal bir soru ortaya çıkıyor: Neden MEVCUTLAR'a ihtiyacımız var ve MEVCUT DEĞİLLER? Cevap, koşulda "her" kelimesini içeren sorguları çözmenin tek yolunun NOT EXISTS olduğudur. Bu tür sorgular ilişkisel cebirde bölme işlemi kullanılarak ve ilişkisel hesaplamada evrensel niceleyici kullanılarak çözülür. Durumunda "her" kelimesinin yer aldığı bir sorgu örneği:

Rica etmek: Her binaya atanan çalışanları listeleyin.

Bu soru SQL'de çift olumsuzlama kullanılarak uygulanabilir. Sorguyu çift negatif içerecek şekilde yeniden formüle edeceğiz:

Rica etmek: Bu tür çalışanları listeleyin Olumsuz atanmadıkları bir bina var.

Çift olumsuzluğu vurguladık. Bu isteğin mantıksal olarak bir öncekine eşdeğer olduğu açıktır.

Şimdi çözümü SQL'de formüle etmek istiyoruz. Nihai çözümün anlaşılmasını kolaylaştırmak için, öncelikle bir ön problemin çözümünü veriyoruz: "1234" adlı varsayımsal bir işçinin bulunduğu tüm binaları belirleme problemi. Olumsuz görevlendirilmiş.

(I) BLDG_ID'Yİ SEÇİN

OLMAYAN YERDE

ATAMA.İŞÇİ_KİMLİĞİ = 1234)

Bu sorguyu (I) işaretledik çünkü ona daha sonra değineceğiz. Bu talebi karşılayan bir bina yoksa her binaya işçi 1234 atanır ve dolayısıyla asıl talebin koşullarını karşılar. Orijinal sorguya çözüm elde etmek için sorguyu (I) belirli bir işçi 1234'ten WORKER_ID değişkenine genellemeli ve bu değiştirilmiş sorguyu daha büyük sorgunun bir alt sorgusuna dönüştürmeliyiz. İşte çözüm:

(II) WORKER_ID'Yİ SEÇİN

OLMAYAN YERDE

OLMAYAN YERDE

NEREDE ATAMA.BLDG_ID = BUILDING.BLDG_ID VE

ASSIGNMENT.WORKER_ID = WORKER.WORKER_ID)

Sonuç:

İŞÇİ KİMLİĞİ

Sorgunun (II) dördüncü satırında başlayan alt sorgunun sorgu (I) ile aynı olduğunu ve "1234"ün WORKER.WORKER_ID ile değiştirildiğini unutmayın. Sorgu (II) şu şekilde okunabilir:

WORKER_ID'nin atanmadığı bina yoksa WORKER'dan WORKER_ID'yi seçin.

Bu, orijinal isteğin koşullarıyla eşleşiyor.

NOT EXISTS operatörünün, ilişkisel cebirde bölme işlemi ve ilişkisel analizde evrensel bir niceleyici gerektiren sorguları formüle etmek için kullanılabileceğini görüyoruz. Kullanım kolaylığı açısından bakıldığında, NOT EXISTS operatörü özel bir fayda sağlamaz; bu, NOT EXISTS'i iki kez kullanan SQL sorgularının anlaşılmasının, bölmeli ilişkisel cebir çözümlerinden veya evrensel niceleyicilerle ilişkisel hesaplama çözümlerinden daha kolay olmadığı anlamına gelir. Bu tür sorguların daha doğal bir şekilde çözülmesine olanak tanıyan dil yapıları oluşturmak için daha fazla araştırmaya ihtiyaç duyulacaktır.

Yerleşik işlevler

Bu tür soruları ele alalım:

Maksimum ve minimum saatlik ücretler nelerdir? 435 no'lu binada çalışanların ortalama çalışma gün sayısı nedir? 312 nolu binanın sıva işi için ayrılan toplam gün sayısı nedir? Kaç farklı uzmanlık var?

Bu soruları yanıtlamak, bir tablodaki birçok satıra bakıp tek bir değer döndüren istatistiksel işlevler gerektirir. SQL'de yerleşik işlevler veya ayarlanmış işlevler adı verilen bu tür beş işlev vardır. Bu işlevler SUM (toplam), AVG (ortalama), COUNT (miktar), MAX (maksimum) ve MIN (minimum) şeklindedir.

Dahili fonksiyon (fonksiyonu ayarlama). Birden fazla satırda çalışan istatistiksel bir fonksiyon: SUM (toplam), AVG (ortalama), COUNT (miktar), MAX (maksimum), MIN (minimum).

Rica etmek: Maksimum ve minimum saatlik ücretler nelerdir?

MAX(HRLY_RATE), MIN(HRLY_RATE) SEÇİN

Sonuç: 17.40, 8.20

MAKS işlevler ve MIN bir tablo sütununda çalışır. Bu sütundan sırasıyla maksimum veya minimum değeri seçerler. Sorgu formülasyonumuz WHERE deyimini içermiyor. Bir sonraki örneğimizin gösterdiği gibi çoğu sorgu için durum böyle olmayabilir.

Rica etmek: 435 no'lu binada çalışanların ortalama çalışma gün sayısı nedir?

AVG'Yİ SEÇİN(NUM_DAYS)

NEREDE BLDG_ID =435

Sonuç: 12.33

Rica etmek: 312 nolu binanın sıva işi için ayrılan toplam gün sayısı nedir?

TOPLAM SEÇ(NUM_DAYS)

GÖREVDEN, İŞÇİ

NEREDE WORKER.WORKER_ID = ATAMA.WORKER_ID VE

SKILL_TYPE = "Sıvacı" VE

Sonuç: 27

Çözüm, ASSIGNMENT ve WORKER tabloları arasında bir birleştirme kullanır. SKILL_TYPE WORKER tablosunda ve BLDG_ID ASSIGNMENT tablosunda olduğundan bu gereklidir.

Rica etmek: Kaç farklı uzmanlık var?

COUNT SEÇİN (DISTINCT SKILL_TYPE)

Sonuç: 4

Aynı uzmanlık birden fazla farklı satırda yer alabileceğinden sistemin aynı uzmanlık türünü birden fazla saymasını önlemek için bu sorguda DISTINCT anahtar sözcüğünü kullanmanız gerekir. DISTINCT operatörü yerleşik işlevlerden herhangi biriyle kullanılabilir, ancak elbette MAX ve MIN işlevleriyle gereksizdir.

BELİRGİN. Yinelenen satırları ortadan kaldıran bir operatör.

SUM ve AVG işlevleri yalnızca sayısal sütunlarla kullanılmalıdır. Diğer işlevler hem sayısal hem de karakter verileriyle kullanılabilir. COUNT dışındaki tüm işlevler hesaplanan ifadelerle kullanılabilir. Örneğin:

Rica etmek: Haftalık ortalama maaş ne kadar?

AVG'Yİ SEÇİN (40 * HRLY_RATE)

Sonuç: 509.14

COUNT tek bir sütun yerine tüm satırı ifade edebilir :

Rica etmek: Kalite seviyesi 3 olan kaç bina var?

SAYIM SEÇ (*)

BİNADAN NEREYE

Sonuç: 3

Tüm bu örneklerin gösterdiği gibi, eğer bir SELECT komutu yerleşik bir işlev içeriyorsa, bu durumda o SELECT komutunda başka hiçbir şey görünemez. Bu kuralın tek istisnası, şimdi bakacağımız GROUP BY deyimidir.

GROUP BY ve HAVING cümleleri

Yönetimde, birçok gruptaki her bir grup hakkında istatistiksel bilgiye sıklıkla ihtiyaç duyulur. Örneğin aşağıdaki sorguyu göz önünde bulundurun:

Rica etmek: Her yönetici için astları arasındaki maksimum saatlik ücreti öğrenin.

Bu sorunu çözebilmek için işçileri yöneticilerine göre gruplara ayırmalıyız. Daha sonra her grup içindeki maksimum teklifi belirleyeceğiz. SQL'de bu şu şekilde yapılır:

SUPV_ID'YE GÖRE GRUPLA

Sonuç:

SUPV_IDMAX(HRLY ORANI)

Bu sorgu işlenirken sistem öncelikle aşağıdaki kuralı kullanarak WORKER tablosunun satırlarını gruplara ayırır. Satırlar, yalnızca aynı SUPV_ID'ye sahip olmaları durumunda aynı gruba yerleştirilir. SELECT yan tümcesi daha sonra her gruba uygulanır. Bu grupta yalnızca bir SUPV_ID değeri bulunduğundan grupta SUPV_ID belirsizliği yoktur. Her grup için, SELECT yan tümcesi SUPV_ID'nin çıktısını verir ve aynı zamanda MAX(HRLY_RATE) değerini hesaplayıp çıktısını verir. Sonuç yukarıda sunulmuştur.

Yerleşik işlevlere sahip bir SELECT komutunda yalnızca GROUP BY yan tümcesinde bulunan sütunlar görünebilir. SUPV_ID'nin GROUP BY yan tümcesinde yer aldığından SELECT komutunda kullanılabileceğini unutmayın.

GROUP BY deyimi. Satırların, belirtilen sütun(lar)ın ortak değerlerine sahip gruplara bölünmesi gerektiğini belirtir.

GROUP BY deyimi belirli karmaşık hesaplamaları gerçekleştirmenize olanak tanır. Örneğin bu maksimum tekliflerin ortalamasını öğrenmek isteyebiliriz. Ancak yerleşik işlevlerle hesaplama, yerleşik işlevlerin diğer yerleşik işlevler içinde kullanılmasına izin vermemesi açısından sınırlıdır. Yani şöyle bir ifade

AVG(MAX(HRLY_RATE))

yasaklı. Böyle bir talebin uygulanması iki aşamadan oluşacaktır. Öncelikle maksimum teklifleri yeni bir tabloya koymamız gerekiyor, ikinci adımda ise ortalamalarını hesaplamamız gerekiyor.

WHERE yan tümcesini GROUP BY komutuyla kullanabilirsiniz:

Rica etmek: Her bina türü için öğrenin ortalama seviye 1. statüdeki binalar arasında kalite.

TÜR SEÇİN, AVG(QLTY_LEVEL)

NEREDE DURUM = 1

Sonuç:

TYPEAVG(QLTY_LEVEL)

Mağaza 1

Konut binası 3

WHERE deyimi GROUP BY deyiminden önce yürütülür. Bu nedenle hiçbir grup, durumu 1'den farklı olan bir satır içeremez. Durum 1 satırları TYPE değerine göre gruplandırılır ve ardından her gruba bir SELECT cümleciği uygulanır.

İfadeye sahip olmak. Gruplara koşullar yerleştirir.

GROUP BY cümleciği tarafından oluşturulan gruplara da koşullar uygulayabiliriz. Bu, HAVING ifadesi kullanılarak yapılır. Örneğin, önceki sorgulardan birini daha spesifik hale getirmeye karar verdiğimizi varsayalım:

Rica etmek: Birden fazla astı bulunan her yönetici için astları arasındaki maksimum saat ücretini bulunuz.

Bu durumu uygun HAVING komutuyla yansıtabiliriz:

SUPV_ID, MAX(HRLY_RATE) SEÇİN

SUPV_ID'YE GÖRE İŞÇİ GRUBUNDAN

SAYISI(*) > 1

Sonuç:

SUPV_ID MAX(HRLY_RATE)

WHERE ve HAVING cümlecikleri arasındaki fark, WHERE'ın satırlara, HAVING'in ise gruplara uygulanmasıdır.

Bir sorgu hem WHERE hem de HAVING yan tümcesini içerebilir. Bu durumda WHERE deyimi gruplamadan önce yürütüldüğü için ilk olarak yürütülür. Örneğin, önceki sorguda aşağıdaki değişikliği göz önünde bulundurun:

Rica etmek: Her bina tipi için, 1. statüdeki binalar arasındaki ortalama kalite seviyesini bulun. Yalnızca maksimum kalite seviyesi 3'ü aşmayan bina türlerini dikkate alın.

TÜRÜ SEÇİN, AVG (QLTY_JLEVEL)

NEREDE DURUM = 1

MAX(QLTY_LEVEL) SAHİBİ<= 3

Sonuç:

TÜR AVG(QLTY_LEVEL)

Mağaza 1

Konut binası 3

FROM yan tümcesinden başlayarak, yan tümcelerin sırayla yürütüldüğünü ve ardından SELECT yan tümcesinin uygulandığını unutmayın. Böylece BUILDING tablosuna WHERE deyimi uygulanır ve STATUS'un 1'den farklı olduğu tüm satırlar silinir. Geri kalan satırlar TÜRE göre gruplandırılmıştır; aynı TYPE değerine sahip tüm satırlar aynı grupta yer alır. Böylece, her TYPE değeri için bir tane olmak üzere çeşitli gruplar oluşturulur. Daha sonra her gruba HAVING deyimi uygulanır ve maksimum kalite düzeyi değeri 3'ü aşan gruplar çıkarılır. Son olarak SELECT yan tümcesi kalan gruplara uygulanır.

7. Yerleşik işlevler ve alt sorgular

Yerleşik işlevler yalnızca SELECT yan tümcesinde veya HAVING komutunda kullanılabilir. Ancak satır içi işlev içeren bir SELECT yan tümcesi bir alt sorgunun parçası olabilir. Böyle bir alt sorgu örneğine bakalım:

Rica etmek: Hangi işçiler ortalamanın üzerinde saatlik ücrete sahip?

WORKER_NAME'İ SEÇİN

WHERE HRLY_RATE >

(AVG'YI SEÇİN(HRLY_RATE)

Sonuç:

H. Columbus

Alt sorgunun ana sorguyla ilişkili olmadığını unutmayın. Alt sorgu tam olarak tek bir değer döndürür; ortalama saatlik ücret. Ana sorgu, bir çalışanı yalnızca ücreti hesaplanan ortalamadan büyükse seçer.

İlişkili sorgular ayrıca yerleşik işlevleri de kullanabilir:

Sorgu: Hangi çalışanın saat ücreti aynı yöneticinin astları arasındaki ortalama saat ücretinden daha yüksek?

Bu durumda, tüm çalışanlar için tek bir ortalama saatlik ücret hesaplamak yerine, aynı yöneticiye bağlı her bir işçi grubu için ortalama ücreti hesaplamamız gerekir. Ayrıca ana sorguda dikkate alınan her çalışan için hesaplamamızın yeniden yapılması gerekmektedir:

A'yı SEÇİN. WORKER_NAME

SQL, sorguları birbirinin içine yerleştirmenize olanak tanır. Tipik olarak bir alt sorgu, yüklemin doğru olup olmadığı kontrol edilen tek bir değer döndürür.

Arama terimi türleri:
. Bir alt sorgunun sonucuyla karşılaştırma (=, >=)
. Bir alt sorgunun (IN) sonuçlarına ait olup olmadığı kontrol ediliyor
. Varlık kontrolü (MEVCUT)
. Çoklu (niceliksel) karşılaştırma (HERHANGİ BİRİ, TÜMÜ)

İç içe geçmiş sorgularla ilgili notlar:
. Bir alt sorgu yalnızca bir sütun seçmelidir (EXISTS yüklemine sahip bir alt sorgu hariç) ve sonuç veri türü, yüklemde belirtilen değerin veri türüyle eşleşmelidir.
. Bazı durumlarda tek bir değerin döndürülmesini sağlamak için DISTINCT anahtar sözcüğünü kullanabilirsiniz.
. Bir alt sorguya ORDER BY veya UNION yan tümcesini ekleyemezsiniz.
. Alt sorgu, arama koşulunun solunda veya sağında bulunabilir.
. Alt sorgular, herhangi bir sayıda satır için otomatik olarak özel bir değer, özel bir IN yüklemi ve sütun tabanlı ifadeler döndüren GROUP BY yan tümcesi olmadan toplama işlevlerini kullanabilir.
. Mümkün olduğunda alt sorgular yerine JOIN tablo birleştirmelerini kullanmalısınız.

İç içe sorgulara örnekler:

SELECT * FROM Orders WHERE SNum=(SELECT SNum FROM SalesPeople WHERE SName='Motika')
* Siparişlerden NEREDE SNum IN SEÇİN (Satıcılardan SNum'u SEÇİN WHERE Şehir='London')
SELECT * FROM Order WHERE SNum=(SELECT DISTINCT SNum FROM Order WHERE CNum=2001)
SELECT * FROM Orders WHERE Amt>(SELECT AVG(Amt) FROM Orders WHERE Odate=10/04/1990)
SELECT * FROM Customer WHERE CNum=(SELECT SNum+1000 FROM SalesPeople WHERE SName='Serres')

2) İlgili alt sorgular

SQL'de, bir dış sorgudan bir tabloya başvuran alt sorgular oluşturabilirsiniz. Bu durumda alt sorgu, dış sorgudaki her tablo satırı için bir kez olmak üzere birden çok kez yürütülür. Bu nedenle alt sorgunun dizini kullanması önemlidir. Bir alt sorgu, dıştaki tabloyla aynı tabloya erişebilir. Dış sorgu nispeten az sayıda satır döndürürse bağlantılı alt sorgu, bağlantısız alt sorgudan daha hızlı olacaktır. Bir alt sorgu az sayıda satır döndürürse ilgili sorgu ilgisiz sorguya göre daha yavaş olacaktır.

İlgili alt sorgulara örnekler:

SELECT * FROM SalesPeople Main WHERE 1(SELECT AVG(Amt) FROM Orders O2 WHERE O2.CNum=O1.CNum) //değeri belirli bir müşteri için ortalama sipariş değerini aşan tüm siparişleri döndürür

3) Yüklem MEVCUTTUR

Söz dizimi formu: VAR ()

Yüklem, bir alt sorguyu bağımsız değişken olarak alır ve alt sorgunun çıktısı varsa doğru, aksi halde yanlış olarak değerlendirir. Alt sorgu bir kez yürütülür ve değerleri kontrol edilmediğinden birkaç sütun içerebilir, ancak satırların varlığının sonucu basitçe kaydedilir.

EXISTS yüklemine ilişkin notlar:
. EXISTS, DOĞRU veya YANLIŞ değerini döndüren bir yüklemdir ve tek başına veya diğer Boole ifadeleriyle birlikte kullanılabilir.
. EXISTS, alt sorgusunda toplama işlevlerini kullanamaz.
. İlişkili alt sorgularda, EXISTS yüklemi dış tablonun her satırı için yürütülür.
. EXISTS yüklemini tablo birleştirmeleriyle birleştirebilirsiniz.

EXISTS yüklemine örnekler:

SELECT * FROM Müşteriden NEREDE VAR(SELECT * FROM Müşteriden WHERE Şehir='San Jose') - herhangi biri San Jose'de yaşıyorsa tüm müşterileri döndürür.
Önce Müşteriden Farklı Snum Seçin NEREDE MEVCUT DEĞİL (SELECT * FROM Customer Send WHERE Send.SNum=First.SNum VE Send.CNumFirst.CNum) – yalnızca bir müşteriye hizmet veren satıcıların sayısını döndürür.
Satış Ekibinden F.SNum, SName, F.Şehir'i AYRICA SEÇİN F, Müşteri S NEREDE MEVCUTTUR (SELECT * FROM Customer T WHERE S.SNum=T.SNum VE S.CNumT.CNum VE F.SNum=S.SNum) – döndürür birden fazla müşteriye hizmet veren tüm satıcıların numaraları, adları ve ikamet ettikleri şehirler.
SELECT * FROM SalesPeople First NEREDE MEVCUTTUR (SELECT * FROM Customer Send WHERE Frst.SNum=Send.SNum VE 1

4) Niceliksel karşılaştırmanın tahminleri

Söz dizimi formu: (=|>|=|) HERHANGİ BİRİ|TÜMÜ ()

Bu yüklemler argüman olarak bir alt sorgu kullanır, ancak EXISTS yüklemi ile karşılaştırıldığında ilişkisel yüklemlerle (=,>=) birlikte kullanılırlar. Bu anlamda IN yüklemine benzerler ancak yalnızca alt sorgularla birlikte kullanılırlar. Standart, HERHANGİ BİR yerine SOME anahtar sözcüğünün kullanılmasına izin verir, ancak tüm DBMS'ler bunu desteklemez.

Karşılaştırma yüklemlerine ilişkin notlar:
. ALL yüklemi, alt sorgunun yürütülmesi sırasında seçilen her değer, dış sorgu yükleminde belirtilen koşulu karşılıyorsa TRUE olarak değerlendirilir. Çoğunlukla eşitsizliklerde kullanılır.
. ANY yüklemi, alt sorgunun yürütülmesi sırasında seçilen en az bir değer, dış sorgu yükleminde belirtilen koşulu karşılıyorsa TRUE olarak değerlendirilir. Çoğunlukla eşitsizliklerde kullanılır.
. Alt sorgu herhangi bir satır döndürmezse, ALL otomatik olarak TRUE değerini alır (karşılaştırma koşulunun karşılandığı kabul edilir), HERHANGİ BİRİ için YANLIŞ değerini alır.
. Hiçbir satır için karşılaştırma DOĞRU ise ve NULL değerine sahip bir veya daha fazla satır varsa, HERHANGİ BİRİ BİLİNMEYEN değerini döndürür.
. Hiçbir satır için karşılaştırma YANLIŞ ise ve NULL değerine sahip bir veya daha fazla satır varsa, TÜMÜ BİLİNMEYEN değerini döndürür.

Niceliksel karşılaştırmanın yüklemi için örnekler:

SEÇİN * Satış Personelinden NEREDE Şehir=HERHANGİ(Müşteriden Şehir SEÇİN)
* Siparişlerden SEÇİN NEREDE TÜMÜ(Müşteriden Derecelendirmeyi SEÇİN WHERE Şehir='Roma')

5) Teklik yüklemi

EŞSİZ|FARKLI ()

Yüklem, alt sorgunun çıktı verilerindeki benzersizliği (kopyaların yokluğunu) kontrol etmek için kullanılır. Ayrıca UNIQUT yükleminde NULL değerlerine sahip dizeler benzersiz kabul edilirken, DISTINCT yükleminde iki tanımsız değer birbirine eşit kabul edilir.

6) Eşleştirme yüklemi

KİBRİT ()

MATCH yüklemi, bir sorgu dizesinin değerinin, alt sorgudan kaynaklanan herhangi bir dizenin değeriyle eşleşip eşleşmeyeceğini test eder. Bu alt sorgu, bazı NULL değerlerine sahip satırlar arasında oluşabilecek "kısmi" (PARTIAL) eşleşmelerin işlenmesine izin vermesi açısından IN AND ANY yüklemlerinden farklıdır.

7) KİMDEN bölümündeki sorgular

Aslında tablo referansına izin verilen her yerde alt sorgu kullanmak yasaldır.

Müşteriden CAdını, Toplam_Amt'ı SEÇİN, (CNum'A GÖRE Siparişlerden TOT_Amt OLARAK CNum, SUM(Amt) SEÇİN) WHERE Şehir='London' VE Müşteri.CNum=Orders.CNum
//alt sorgu, her müşterinin Londra'dan verdiği siparişlerin toplam miktarını döndürür.

8) Özyinelemeli sorgular

ÖZYİNELİ İLE
Q1 SEÇİM OLARAK… NEREDEN… NEREDEN…
Q2 SEÇİM OLARAK… NEREDEN… NEREDEN…




Tepe