Tüm Ürünler
Search
Belge Merkezi

MaxCompute:Alt Sorgular

Son Güncelleme:Oct 04, 2026

Alt sorgu, başka bir sorgunun içinde yer alan bir SELECT ifadesidir ve diğer sorguların sonuç kümelerini sorgulamanıza olanak tanır. Toplam değerlerin hesaplanması, satır varlığının kontrol edilmesi, başka bir sorgunun sonucuna göre verilerin filtrelenmesi, ilişkili güncelleme veya silme işlemlerinin yapılması, tek bir değer döndürmek için JOIN işleminin basitleştirilmesi, sonucun dış sorgu için türetilmiş tablo olarak kullanılması, sıralama veya gruplama temeli sağlanması ve satır bazlı karşılaştırmaların yapılması yaygın kullanım durumlarıdır. Bu konu, MaxCompute'in desteklediği alt sorgu türlerini ve bunların nasıl kullanılacağını açıklar.

Özellikler

MaxCompute aşağıdaki alt sorgu türlerini destekler:

  • Temel alt sorgu

    Temel alt sorgu, bir sorgunun FROM yan tümcesinde kullanılır ve türetilmiş tablo olarak işlev görür. Sorgu içindeki karmaşık hesaplamalar veya veri dönüşümleri için bu türü kullanabilirsiniz.

  • IN alt sorgusu

    Dış sorgudan, alt sorgu tarafından döndürülen değer kümesiyle eşleşen satırları seçmek için WHERE yan tümcesinde IN alt sorgusu kullanın.

  • NOT IN alt sorgusu

    NOT IN alt sorgusu, dış sorgudan alt sorgunun sonuç kümesiyle eşleşen satırları kaldırmak için WHERE yan tümcesinde kullanılır.

  • EXISTS alt sorgusu

    EXISTS alt sorgusu, alt sorgunun herhangi bir satır döndürüp döndürmediğini test eder. İçerdikleri gerçek verilere ihtiyaç duymadan ilişkili satırların varlığını kontrol etmek için bu tür uygundur.

  • NOT EXISTS alt sorgusu

    NOT EXISTS alt sorgusu, dış sorgudan alt sorguda eşleşmesi olmayan satırları seçer.

  • Skaler alt sorgu

    Skaler alt sorgu tek bir değer (tek satır ve tek sütun) döndürür. Genellikle SELECT listesinde veya WHERE ya da HAVING yan tümcesinde koşul değeri olarak kullanılır.

Not

Çalıştırma sırasında, sorgu optimize edicisi genellikle skaler, IN, NOT IN, EXISTS veya NOT EXISTS gibi bazı alt sorguları JOIN işlemlerine dönüştürür. MAPJOIN, verimli bir broadcast join algoritmasıdır. Bir alt sorgunun sonucunun küçük bir tablo olduğunu belirlerseniz, MAPJOIN algoritmasını açıkça kullanmak için alt sorguya bir ipucu ekleyebilirsiniz. Daha fazla bilgi için bkz. SUBQUERY_MAPJOIN İPUCU.

Örnek veriler

Bu konudaki örnekler, sale_detail adlı bölümlenmiş bir tablo kullanır. Tabloyu oluşturup doldurmak için aşağıdaki ifadeleri çalıştırın:

-- Create a partitioned table named sale_detail
CREATE TABLE IF NOT EXISTS sale_detail
(
  shop_name     string,
  customer_id   string,
  total_price   double
)
PARTITIONED BY (sale_date string, region string);

-- Add partitions
ALTER TABLE sale_detail ADD
  PARTITION (sale_date='2013', region='china')
  PARTITION (sale_date='2014', region='shanghai');

-- Insert data
INSERT INTO sale_detail PARTITION (sale_date='2013', region='china')
  VALUES ('s1','c1',100.1),('s2','c2',100.2),('s3','c3',100.3);

INSERT INTO sale_detail PARTITION (sale_date='2014', region='shanghai')
  VALUES ('null','c5',null),('s6','c6',100.4),('s7','c7',100.5);

Tablonun tamamını görüntülemek için:

SET odps.sql.allow.fullscan=true;
SELECT * FROM sale_detail;
+------------+-------------+-------------+------------+------------+
| shop_name  | customer_id | total_price | sale_date  | region     |
+------------+-------------+-------------+------------+------------+
| s1         | c1          | 100.1       | 2013       | china      |
| s2         | c2          | 100.2       | 2013       | china      |
| s3         | c3          | 100.3       | 2013       | china      |
| null       | c5          | NULL        | 2014       | shanghai   |
| s6         | c6          | 100.4       | 2014       | shanghai   |
| s7         | c7          | 100.5       | 2014       | shanghai   |
+------------+-------------+-------------+------------+------------+

Temel alt sorgu

Standart bir sorgu ana bir tablo üzerinde çalışır. Ancak, bir sorgu başka bir select ifadesi üzerinde de çalışabilir. Bu tür sorguya alt sorgu denir. from yan tümcesinde, alt sorgu bir tablo olarak ele alınabilir ve bir join işlemi kullanılarak diğer tablolarla veya alt sorgularla birleştirilebilir. join işlemleri hakkında daha fazla bilgi için bkz. JOIN.

  • Sözdizimi

    select <select_expr> from (<select_statement>) [<sq_alias_name>];
  • Parametreler

    • select_expr: Gereklidir. Format col1_name, col2_name, regular expression,... şeklindedir; sorgulanacak normal sütunları, bölüm anahtar sütunlarını veya düzenli ifadeleri belirtir.

    • select_statement: Gereklidir. Alt sorgu ifadesi. Format hakkında daha fazla bilgi için bkz. SELECT sözdizimi.

    • sq_alias_name: İsteğe bağlıdır. Alt sorgunun takma adı.

    • table_name: Gereklidir. Ana tablonun adı.

  • Örnekler

    • Örnek 1: Aşağıdaki komut temel alt sorgu sözdizimine bir örnek sunar.

      set odps.sql.allow.fullscan=true;
      select * from (select shop_name from sale_detail) a;

      Sonuç:

      +------------+
      | shop_name  |
      +------------+
      | s1         |
      | s2         |
      | s3         |
      | null       |
      | s6         |
      | s7         |
      +------------+
    • Örnek 2: from yan tümcesinde, alt sorgu bir tablo olarak ele alınabilir ve diğer tablolarla veya alt sorgularla bir join işleminde kullanılabilir. Örnek bir komut aşağıdaki gibidir.

      -- Create a table and then perform a join operation.
      create table shop as select shop_name,customer_id,total_price from sale_detail;
      select a.shop_name, a.customer_id, a.total_price from
      (select * from shop) a join sale_detail on a.shop_name = sale_detail.shop_name;

      Sonuç:

      +------------+-----------------+-----------------+
      | _c0        | scalarsubquery1 | scalarsubquery2 |
      +------------+-----------------+-----------------+
      | null       | c5              | NULL            |
      | s6         | c6              | 100.4           |
      | s7         | c7              | 100.5           |
      | s1         | c1              | 100.1           |
      | s2         | c2              | 100.2           |
      | s3         | c3              | 100.3           |
      +------------+-----------------+-----------------+

IN alt sorgusu

in subquery left semi join ile benzer şekilde kullanılır.

  • Sözdizimi

    • Format 1

      select <select_expr1> from <table_name1> where <select_expr2> in (select <select_expr3> from <table_name2>);
      -- This statement is equivalent to the following LEFT SEMI JOIN statement.
      select <select_expr1> from <table_name1> <alias_name1> left semi join <table_name2> <alias_name2> on <alias_name1>.<select_expr2> = <alias_name2>.<select_expr3>;
      Not

      Eğer select_expr2 bir bölüm anahtar sütunu ise, alt sorgu select <select_expr2> from <table_name2> ayrı bir işte çalıştırılır ve bir semi join işlemine dönüştürülmez. Çalıştırma sonuçları daha sonra select_expr2 ile karşılaştırılır. table_name1 içindeki bölümlerin select_expr2 değerleri döndürülen sonuçlarda yoksa okunmaz. Bu sayede bölüm budama etkili kalır.

    • Format 2

      MaxCompute yalnızca in subquery değil, aynı zamanda ilişkili koşulları da destekler. Alt sorgudaki where <table_name2_colname> = <table_name1>.<colname> yan tümcesi ilişkili bir koşuldur. MaxCompute 1.0, hem alt sorgudaki kaynak tabloya hem de dış sorgudaki kaynak tabloya başvuran ifadeleri desteklemiyordu. MaxCompute 2.0 bu kullanımı destekler; burada bu filtre koşulu, bir semi join içindeki on koşulunun bir parçasını oluşturur.

      select <select_expr1> from <table_name1> where <select_expr2> in (select <select_expr3> from <table_name2> where
      <table_name1>.<col_name> = <table_name2>.<col_name>);
      Not

      MaxCompute, bir join koşulu olarak kullanılmayan bir in subquery öğesini destekler; örneğin, bir where yan tümcesinin dışında yer alıyorsa veya bir where yan tümcesinde yer alıp bir join koşuluna dönüştürülemiyorsa. Bu durumda, alt sorgu bir semi join işlemine dönüştürülemez, alt sorguyu çalıştırmak için ayrı bir iş başlatılmalıdır ve ilişkili koşullar desteklenmez.

    • Format 3

      Yukarıdaki yeteneklere dayanarak, MaxCompute PostgreSQL'in çoklu sütun desteğiyle uyumludur. Uygulamayı birden fazla alt sorguya ayırmaya kıyasla, bu yaklaşım bir JOIN sürecini azaltır ve hesaplama kaynaklarından tasarruf sağlar. Desteklenen çoklu sütun kullanımları aşağıdaki gibidir:

      • in ifadesinden sonra gelen ifade, basit bir çoklu sütunlu SELECT ifadesi olabilir.

      • in ifadesinden sonra gelen ifadeye toplama işlevleri ekleyebilirsiniz. Daha fazla bilgi için bkz. Toplama işlevleri.

      • in ifadesinden sonraki ifade bir sabit olabilir.

  • Parametreler

    • select_expr1: Gereklidir. Format col1_name, col2_name, regular expression,... şeklindedir. Bu parametre, sorgulanacak normal sütunları, bölüm anahtar sütunlarını veya düzenli ifadeleri belirtir.

    • table_name1, table_name2: Gereklidir. Tabloların adları.

    • select_expr2, select_expr3: Gereklidir. table_name1 ve table_name2 tablolarının eşleştirilmiş sütun adları.

    • col_name: Gereklidir. Bir sütunun adı.

  • Kullanım notları

    IN içeren bir alt sorgu kullanırken, NULL değerlere sahip satırlar otomatik olarak alt sorgunun sonuç kümesinden kaldırılır.

  • Örnekler

    • Örnek 1: Format 1'in alt sorgu sözdizimini kullanın.

      set odps.sql.allow.fullscan=true;
      select * from sale_detail where total_price in (select total_price from shop);

      Sonuç:

      +-----------+-------------+-------------+-----------+--------+
      | shop_name | customer_id | total_price | sale_date | region |
      +-----------+-------------+-------------+-----------+--------+
      | s1        | c1          | 100.1       | 2013      | china  |
      | s2        | c2          | 100.2       | 2013      | china  |
      | s3        | c3          | 100.3       | 2013      | china  |
      | s6        | c6          | 100.4       | 2014      | shanghai |
      | s7        | c7          | 100.5       | 2014      | shanghai |
      +-----------+-------------+-------------+-----------+--------+
    • Örnek 2: Format 2'nin alt sorgu sözdizimini kullanın.

      set odps.sql.allow.fullscan=true;
      select * from sale_detail where total_price in (select total_price from shop where customer_id = shop.customer_id);

      Sonuç:

      +-----------+-------------+-------------+-----------+--------+
      | shop_name | customer_id | total_price | sale_date | region |
      +-----------+-------------+-------------+-----------+--------+
      | s1        | c1          | 100.1       | 2013      | china  |
      | s2        | c2          | 100.2       | 2013      | china  |
      | s3        | c3          | 100.3       | 2013      | china  |
      | s6        | c6          | 100.4       | 2014      | shanghai |
      | s7        | c7          | 100.5       | 2014      | shanghai |
      +-----------+-------------+-------------+-----------+--------+
    • Örnek 3: Çoklu sütunlu SELECT ifadesi kullanma.

      -- For easier understanding, sample data is reconstructed here.
      create table if not exists t1(a bigint,b bigint,c bigint,d bigint,e bigint);
      create table if not exists t2(a bigint,b bigint,c bigint,d bigint,e bigint);
      insert into table t1 values (1,3,2,1,1),(2,2,1,3,1),(3,1,1,1,1),(2,1,1,0,1),(1,1,1,0,1);
      insert into table t2 values (1,3,5,0,1),(2,2,3,1,1),(3,1,1,0,1),(2,1,1,0,1),(1,1,1,0,1);
      -- Scenario 1: The expression after `in` is a simple multi-column SELECT statement.
      select a, b from t1 where (c, d) in (select a, b from t2 where e = t1.e);
      -- The following result is returned.
      +------------+------------+
      | a          | b          |
      +------------+------------+
      | 1          | 3          |
      | 2          | 2          |
      | 3          | 1          |
      +------------+------------+
      -- Scenario 2: Use an aggregate function in the expression after `in`.
      select a, b from t1 where (c, d) in (select max(a), b from t2 where e = t1.e group by b having max(a) > 0);
      -- The following result is returned.
      +------------+------------+
      | a          | b          |
      +------------+------------+
      | 2          | 2          |
      +------------+------------+
      -- Scenario 3: The expression after `in` is a constant.
      select a, b from t1 where (c, d) in ((1, 3), (1, 1));
      -- The following result is returned.
      +------------+------------+
      | a          | b          |
      +------------+------------+
      | 2          | 2          |
      | 3          | 1          |
      +------------+------------+

NOT IN alt sorgusu

not in subquery left anti join ile benzerdir, ancak özdeş değildir. Alt sorgu tarafından döndürülen belirtilen sütun herhangi bir NULL değer içeriyorsa, not in ifadesi NULL olarak değerlendirilir. Bu durum where koşulunun başarısız olmasına ve hiçbir veri döndürülmemesine neden olur. Bu durum left anti join işleminden farklıdır.

  • Sözdizimi

    • Format 1

      select <select_expr1> from <table_name1> where <select_expr2> not in (select <select_expr2> from <table_name2>);
      -- This statement is equivalent to the following LEFT ANTI JOIN statement.
      select <select_expr1> from <table_name1> <alias_name1> left anti join <table_name2> <alias_name2> on <alias_name1>.<select_expr1> = <alias_name2>.<select_expr2>;
      Not

      Eğer select_expr2 bir bölüm anahtar sütunu ise, select <select_expr2> from <table_name2> alt sorgusu ayrı bir işte çalıştırılır ve bir anti join işlemine dönüştürülmez. Çalıştırma sonucu, select_expr2 değerleriyle karşılaştırılır. Döndürülen sonuç kümesinde select_expr2 değerleri bulunmayan table_name1 içindeki bölümler okunmaz; bu sayede bölüm budama etkili kalır.

    • Format 2

      MaxCompute yalnızca NOT IN alt sorgularını değil, aynı zamanda ilişkili koşulları da destekler. Alt sorgudaki where <table_name2_colname> = <table_name1>.<colname> yan tümcesi ilişkili bir koşuldur. MaxCompute 1.0, hem alt sorgudaki kaynak tabloya hem de dış sorgunun kaynak tablosuna başvuran ifadeleri desteklemiyordu. MaxCompute 2.0 bu kullanımı destekler. Bu filtre koşulu, bir ANTI JOIN içindeki ON koşulunun bir parçasını oluşturur.

      select <select_expr1> from <table_name1> where <select_expr2> not in (select <select_expr2> from <table_name2> where <table_name2_colname> = <table_name1>.<colname>);
      Not

      MaxCompute, bir join koşulu olarak kullanılmadığında not in subquery öğesini destekler; örneğin, bir where yan tümcesinin dışında yer alıyorsa veya bir where yan tümcesinde yer alıp bir join koşuluna dönüştürülemiyorsa. Bu durumda, bir anti join işlemine dönüştürülemez. Alt sorguyu çalıştırmak için ayrı bir iş başlatılmalıdır ve ilişkili koşullar desteklenmez.

    • Format 3

      Yukarıdaki yeteneklere dayanarak, MaxCompute PostgreSQL'in çoklu sütun desteğiyle uyumludur. Uygulamayı birden fazla alt sorguya ayırmaya kıyasla, bu yaklaşım bir JOIN sürecini azaltır ve hesaplama kaynaklarından tasarruf sağlar. Desteklenen çoklu sütun kullanımları aşağıdaki gibidir:

      • not in ifadesinden sonraki ifade, birden fazla sütun döndüren basit bir SELECT ifadesi olabilir.

      • not in ifadesini takip eden bir ifadeye toplama işlevleri ekleyebilirsiniz. Daha fazla bilgi için bkz. Toplama işlevleri.

      • not in ifadesini takip eden ifade bir sabit olabilir.

  • Parametreler

    • select_expr1: Gereklidir. Format col1_name, col2_name, regular expression,... şeklindedir. Bu parametre, sorgulanacak normal sütunları, bölüm anahtar sütunlarını veya düzenli ifadeleri belirtir.

    • table_name1, table_name2: Gereklidir. Tabloların adları.

    • select_expr2, select_expr3: Gereklidir. table_name1 ve table_name2 tablolarının eşleştirilmiş sütun adları.

    • col_name: Gereklidir. Bir sütunun adı.

  • Kullanım notları

    NOT IN içeren bir alt sorgu kullanırken, NULL değerlere sahip satırlar otomatik olarak alt sorgunun sonuç kümesinden kaldırılır.

  • Örnekler

    • Örnek 1: Format 1'in alt sorgu sözdizimini kullanın.

      -- Create a new table named shop1 and insert data into it.
      create table shop1 as select shop_name,customer_id,total_price from sale_detail;
      insert into shop1 values ('s8','c1',100.1);
      
      select * from shop1 where shop_name not in (select shop_name from sale_detail);

      Sonuç:

      +------------+-------------+-------------+
      | shop_name  | customer_id | total_price |
      +------------+-------------+-------------+
      | s8         | c1          | 100.1       |
      +------------+-------------+-------------+
    • Örnek 2: Format 2'nin alt sorgu sözdizimini kullanın.

      set odps.sql.allow.fullscan=true;
      select * from shop1 where shop_name not in (select shop_name from sale_detail where customer_id = shop1.customer_id);

      Sonuç:

      +------------+-------------+-------------+
      | shop_name  | customer_id | total_price |
      +------------+-------------+-------------+
      | s8         | c1          | 100.1       |
      +------------+-------------+-------------+
    • Örnek 3: not in subquery bir join koşulu olarak kullanılmaz. Aşağıda bir komut örneği verilmiştir.

      set odps.sql.allow.fullscan=true;
      select * from shop1 where shop_name not in (select shop_name from sale_detail) and total_price < 100.3;

      where yan tümcesi and içerdiğinden, sorgu bir anti join işlemine dönüştürülemez ve bunun yerine ayrı bir işte alt sorgu olarak çalıştırılır.

      Sonuç:

      +------------+-------------+-------------+
      | shop_name  | customer_id | total_price |
      +------------+-------------+-------------+
      | s8         | c1          | 100.1       |
      +------------+-------------+-------------+
    • Örnek 4: Alt sorgu sonucu bir NULL değer içeriyorsa, hiçbir veri döndürülmez. Aşağıdaki komut buna bir örnek sunar.

      -- Create a new table named sale and insert data into it.
      create table if not exists sale
      (
      shop_name     string,
      customer_id   string,
      total_price   double
      )
      partitioned by (sale_date string, region string);
      alter table sale add partition (sale_date='2013', region='china');
      insert into sale partition (sale_date='2013', region='china') values ('null','null',null),('s2','c2',100.2),('s3','c3',100.3),('s8','c8',100.8);
      
      set odps.sql.allow.fullscan=true;
      select * from sale where shop_name not in (select shop_name from sale_detail);

      Sonuç:

      +------------+-------------+-------------+------------+------------+
      | shop_name  | customer_id | total_price | sale_date  | region     |
      +------------+-------------+-------------+------------+------------+
      +------------+-------------+-------------+------------+------------+
    • Örnek 5: Çoklu sütunlu SELECT ifadesi kullanma.

      -- For easier understanding, sample data is reconstructed here. This data is the same as the sample data in the IN subquery section.
      create table if not exists t1(a bigint,b bigint,c bigint,d bigint,e bigint);
      create table if not exists t2(a bigint,b bigint,c bigint,d bigint,e bigint);
      insert into table t1 values (1,3,2,1,1),(2,2,1,3,1),(3,1,1,1,1),(2,1,1,0,1),(1,1,1,0,1);
      insert into table t2 values (1,3,5,0,1),(2,2,3,1,1),(3,1,1,0,1),(2,1,1,0,1),(1,1,1,0,1);
      -- Scenario 1: The expression after `not in` is a simple multi-column SELECT statement.
      select a, b from t1 where (c, d) not in (select a, b from t2 where e = t1.e);
      -- The following result is returned.
      +------------+------------+
      | a          | b          |
      +------------+------------+
      | 2          | 1          |
      | 1          | 1          |
      +------------+------------+
      -- Scenario 2: Use an aggregate function in the expression after `not in`.
      select a, b from t1 where (c, d) not in (select max(a), b from t2 where e = t1.e group by b having max(a) > 0);
      -- The following result is returned.
      +------------+------------+
      | a          | b          |
      +------------+------------+
      | 1          | 3          |
      | 3          | 1          |
      | 2          | 1          |
      | 1          | 1          |
      +------------+------------+
      -- Scenario 3: The expression after `not in` is a constant.
      select a, b from t1 where (c, d) not in ((1, 3), (1, 1));
      -- The following result is returned.
      +------------+------------+
      | a          | b          |
      +------------+------------+
      | 1          | 3          |
      | 2          | 1          |
      | 1          | 1          |
      +------------+------------+

EXISTS alt sorgusu

Bir exists subquery kullandığınızda, alt sorguda en az bir satır veri varsa True, aksi takdirde False döner.

MaxCompute yalnızca ilişkili koşullar içeren where alt sorgularını destekler. Bir exists subquery bir left semi join olarak uygulanır.

  • Sözdizimi

    select <select_expr> from <table_name1> where exists (select <select_expr> from <table_name2> where <table_name2_colname> = <table_name1>.<colname>);
  • Parametreler

    • select_expr: Gereklidir. Format col1_name, col2_name, regular expression,... şeklindedir; sorgulanacak normal sütunları, bölüm anahtar sütunlarını veya düzenli ifadeleri belirtir.

    • table_name1, table_name2: Gereklidir. Tabloların adları.

    • col_name: Gereklidir. Bir sütunun adı.

  • Örnek

    set odps.sql.allow.fullscan=true;
    select * from sale_detail where exists (select * from shop where customer_id = sale_detail.customer_id);
    -- This statement is equivalent to the following statement.
    select * from sale_detail a left semi join shop b on a.customer_id = b.customer_id;

    Sonuç:

    +------------+-------------+-------------+------------+------------+
    | shop_name  | customer_id | total_price | sale_date  | region     |
    +------------+-------------+-------------+------------+------------+
    | null       | c5          | NULL        | 2014       | shanghai   |
    | s6         | c6          | 100.4       | 2014       | shanghai   |
    | s7         | c7          | 100.5       | 2014       | shanghai   |
    | s1         | c1          | 100.1       | 2013       | china      |
    | s2         | c2          | 100.2       | 2013       | china      |
    | s3         | c3          | 100.3       | 2013       | china      |
    +------------+-------------+-------------+------------+------------+

NOT EXISTS alt sorgusu

Bir not exists subquery kullandığınızda, alt sorguda veri yoksa True döner. Aksi takdirde False döner.

MaxCompute yalnızca ilişkili koşul içeren where alt sorgularını destekler. Bir not exists subquery bir left anti join olarak uygulanır.

  • Sözdizimi

    select <select_expr> from <table_name1> where not exists (select <select_expr> from <table_name2> where <table_name2_colname> = <table_name1>.<colname>);
  • Parametreler

    • select_expr: Gereklidir. Format col1_name, col2_name, regular expression,... şeklindedir; sorgulanacak normal sütunları, bölüm anahtar sütunlarını veya düzenli ifadeleri belirtir.

    • table_name1, table_name2: Gereklidir. Tabloların adları.

    • col_name: Gereklidir. Bir sütunun adı.

  • Örnek

    set odps.sql.allow.fullscan=true;
    select * from sale_detail where not exists (select * from shop where shop_name = sale_detail.shop_name);
    -- This statement is equivalent to the following statement.
    select * from sale_detail a left anti join shop b on a.shop_name = b.shop_name;

    Sonuç:

    +------------+-------------+-------------+------------+------------+
    | shop_name  | customer_id | total_price | sale_date  | region     |
    +------------+-------------+-------------+------------+------------+
    +------------+-------------+-------------+------------+------------+

Skaler alt sorgu

Bir alt sorgu tek bir satır ve tek bir sütun döndürüyorsa, skaler işlemlerde skaler değer olarak kullanılabilir. Bir sorgu yalnızca bir satır döndürüyorsa, sonucu değiştirmeden sorguyu bir max veya min işlevi içine alabilirsiniz. Skaler alt sorgular ayrıca çoklu sütun kullanımını destekler. Örneğin, bir skaler alt sorgu SELECT listesinde çoklu sütunlu ifade olarak kullanılabilir, ancak yalnızca eşitlik ifadeleri desteklenir. Ayrıca SELECT listesinde bir BOOLEAN ifadesi olarak da kullanılabilir, ancak yalnızca eşitlik karşılaştırmaları için geçerlidir. where yan tümcesinde çoklu sütun karşılaştırmaları desteklenir, ancak yalnızca eşitlik için geçerlidir.

  • Sözdizimi

    • Format 1

      select <select_expr> from <table_name1> where (<select count(*) from <table_name2> where <table_name2_colname> = <table_name1>.<colname>) <scalar_operator> <scalar_value>;
      -- This statement is equivalent to the following statement.
      select <table_name1>.<select_expr> from <table_name1> left semi join (select <colname>, count(*) from <table_name2> group by <colname> having count(*) <scalar_operator> <scalar_value>) <table_name2> on <table_name1>.<colname> = <table_name2>.<colname>;
      Not
      • select count(*) from <table_name2> where <table_name2_colname> = <table_name1>.<colname> çıktısı bir satır kümesidir. Bu ifade yalnızca bir satır ve bir sütun döndürür. Bu nedenle, skaler olarak ele alınabilir. Ancak uygulama sırasında, mümkün olduğunca bir join işlemine dönüştürülür.

      • Derleyici, derleme zamanında tam olarak bir satır ve bir sütun döndürdüğünü teyit edebiliyorsa bir alt sorgu skaler olarak kullanılabilir. Bu durum yalnızca çalışma zamanında belirlenebiliyorsa, derleyici hata döndürür. İfadenin derleyici tarafından kabul edilmesi için iki gereksinimi karşılaması gerekir:

        • Alt sorgunun SELECT listesi, tablo değerli işlevin parametre listesinde olmayan bir toplama işlevi kullanır.

        • Toplama işlevi içeren alt sorguda bir group by yan tümcesi bulunmaz.

    • Format 2

      select (<select_statement>) from <table_name>;
  • Parametreler

    • select_expr: Gereklidir. Format col1_name, col2_name, regular expression,... şeklindedir; sorgulanacak normal sütunları, bölüm anahtar sütunlarını veya düzenli ifadeleri belirtir.

    • table_name1, table_name2: Gereklidir. Tabloların adları.

    • col_name: Gereklidir. Bir sütunun adı.

    • scalar_operator: Gereklidir. Örneğin, büyüktür (>), küçüktür (<), eşittir (=), büyük eşittir (>=) veya küçük eşittir (<=).

    • scalar_value: Gereklidir. Skaler bir değer.

    • select_statement: Gereklidir. Alt sorgu ifadesi. Format 2'yi kullanıyorsanız, alt sorgu yalnızca bir satır döndürmelidir. Format hakkında daha fazla bilgi için bkz. SELECT sözdizimi.

  • Sınırlamalar

    • Bir scalar subquery dış sorgudan sütunlara başvurabilir, ancak birden fazla scalar subquery ifadesi iç içe geçtiğinde, bir alt sorgu yalnızca kendisine en yakın dış sorgudan sütunlara başvurabilir.

      -- Allowed operation.
      select * from t1 where (select count(*) from t2 where t1.a = t2.a) = 3; 
      -- Disallowed operation. The nested subquery references `t1.a`, which is two levels out, not from the immediate outer layer.
      select * from t1 where (select count(*) from t2 where (select count(*) from t3 where t3.a = t1.a) = 2) = 3; 
  • Örnekler

    • Örnek 1: Aşağıdaki komut yaygın bir kullanım durumuna örnek sunar.

      set odps.sql.allow.fullscan=true;
      select * from shop where (select count(*) from sale_detail where sale_detail.shop_name = shop.shop_name) >= 1;

      Sonuç:

      +------------+-------------+-------------+
      | shop_name  | customer_id | total_price |
      +------------+-------------+-------------+
      | s1         | c1          | 100.1       |
      | s2         | c2          | 100.2       |
      | s3         | c3          | 100.3       |
      | null       | c5          | NULL        |
      | s6         | c6          | 100.4       |
      | s7         | c7          | 100.5       |
      +------------+-------------+-------------+
    • Örnek 2: Çoklu sütunlu SELECT ifadesi kullanma.

      -- For easier understanding, sample data is reconstructed here.
      create table if not exists ts(a bigint,b bigint,c double);
      create table if not exists t(a bigint,b bigint,c double);
      insert into table ts values (1,3,4.0),(1,3,3.0);
      insert into table t values (1,3,4.0),(1,3,5.0);
      -- Scenario 1: A SELECT column is a scalar subquery expression with multiple columns. Only equality expressions are supported. Invalid usage: `select (select a, b from t where c > ts.c) as (a, b), a from ts;`
      select (select a, b from t where c = ts.c) as (a, b), a from ts;
      -- The following result is returned.
      +------------+------------+------------+
      | a          | b          | a2         |
      +------------+------------+------------+
      | 1          | 3          | 1          |
      | NULL       | NULL       | 1          |
      +------------+------------+------------+
      -- Scenario 2: The SELECT column is a Boolean expression. Only equality comparisons are supported. Invalid usage: `select (a,b) > (select a,b from ts where c = t.c) from t;`
      select (a,b) = (select a,b from ts where c = t.c) from t;
      -- The following result is returned.
      +------+
      | _c0  |
      +------+
      | true |
      | false |
      +------+
      -- Scenario 3: The `where` clause supports multi-column comparisons. Only equality comparisons are supported. Invalid usage: `select * from t where (a,b) > (select a,b from ts where c = t.c);`
      select * from t where c > 3.0 and (a,b) = (select a,b from ts where c = t.c);
      -- The following result is returned.
      +------------+------------+------------+
      | a          | b          | c          |
      +------------+------------+------------+
      | 1          | 3          | 4.0        |
      +------------+------------+------------+
      select * from t where c > 3.0 or (a,b) = (select a,b from ts where c = t.c);
      -- The following result is returned.
      +------------+------------+------------+
      | a          | b          | c          |
      +------------+------------+------------+
      | 1          | 3          | 4.0        |
      | 1          | 3          | 5.0        |
      +------------+------------+------------+
    • Örnek 3: Format 2'nin alt sorgu sözdizimini kullanma.

      set odps.sql.allow.fullscan=true;
      select (select * from sale_detail where shop_name='s1') from sale_detail;

      Sonuç:

      +------------+-----------------+-----------------+-----------------+-----------------+
      | _c0        | scalarsubquery1 | scalarsubquery2 | scalarsubquery3 | scalarsubquery4 |
      +------------+-----------------+-----------------+-----------------+-----------------+
      | s1         | c1              | 100.1           | 2013            | china           |
      | s1         | c1              | 100.1           | 2013            | china           |
      | s1         | c1              | 100.1           | 2013            | china           |
      | s1         | c1              | 100.1           | 2013            | china           |
      | s1         | c1              | 100.1           | 2013            | china           |
      | s1         | c1              | 100.1           | 2013            | china           |
      +------------+-----------------+-----------------+-----------------+-----------------+

İlgili konular

Alt sorguların aşırı kullanılması veya verimsiz yazılması, özellikle büyük veri ortamlarında sorgu performansını düşürebilir. Sorgu verimliliğini artırmak için geçici tablo, materyalize edilmiş görünüm gibi alternatifleri göz önünde bulundurun veya birden fazla alt sorguyu JOIN işlemlerine yeniden yapılandırın. Daha fazla bilgi için bkz. Materyalize edilmiş görünümler ve JOIN.