Przykłady podzapytań SQL dla Azure Cosmos DBSQL subquery examples for Azure Cosmos DB

Podzapytanie jest zagnieżdżona w innym zapytaniu.A subquery is a query nested within another query. Podzapytanie jest również nazywane zapytaniem wewnętrznym lub zaznaczeniem wewnętrznym.A subquery is also called an inner query or inner select. Instrukcja zawierająca podzapytanie jest zazwyczaj nazywana zewnętrznym zapytaniem.The statement that contains a subquery is typically called an outer query.

W tym artykule opisano podzapytania SQL i ich typowe przypadki użycia w programie Azure Cosmos DB.This article describes SQL subqueries and their common use cases in Azure Cosmos DB. Wszystkie przykładowe zapytania w tym dokumencie można uruchomić względem zestawu danych odżywiania, który jest wstępnie załadowany na Azure Cosmos DB środowisko testowe zapytań.All sample queries in this doc can be run against a nutrition dataset that is preloaded on the Azure Cosmos DB Query Playground.

Typy podzapytańTypes of subqueries

Istnieją dwa główne typy podzapytań:There are two main types of subqueries:

  • Skorelowane: podzapytanie, które odwołuje się do wartości z zapytania zewnętrznego.Correlated: A subquery that references values from the outer query. Podzapytanie jest oceniane raz dla każdego wiersza, który przetwarza zapytanie zewnętrzne.The subquery is evaluated once for each row that the outer query processes.
  • Nieskorelowane: podzapytanie, które jest niezależne od zapytania zewnętrznego.Non-correlated: A subquery that's independent of the outer query. Może być uruchamiany samodzielnie bez polegania na zewnętrznym zapytaniu.It can be run on its own without relying on the outer query.

Uwaga

Azure Cosmos DB obsługuje tylko skorelowane podzapytania.Azure Cosmos DB supports only correlated subqueries.

Podzapytania można zaklasyfikować w oparciu o liczbę wierszy i kolumn, które zwracają.Subqueries can be further classified based on the number of rows and columns that they return. Istnieją trzy typy:There are three types:

  • Tabela: zwraca wiele wierszy i wiele kolumn.Table: Returns multiple rows and multiple columns.
  • Wiele wartości: zwraca wiele wierszy i pojedynczą kolumnę.Multi-value: Returns multiple rows and a single column.
  • Skalarny: zwraca pojedynczy wiersz i pojedynczą kolumnę.Scalar: Returns a single row and a single column.

Zapytania SQL w Azure Cosmos DB zawsze zwracają pojedynczą kolumnę (prostą lub złożoną).SQL queries in Azure Cosmos DB always return a single column (either a simple value or a complex document). W związku z tym w Azure Cosmos DB są stosowane tylko wielowartościowe i skalarne podzapytania.Therefore, only multi-value and scalar subqueries are applicable in Azure Cosmos DB. Można użyć wielowartościowego podzapytania tylko w klauzuli FROM jako wyrażenia relacyjnego.You can use a multi-value subquery only in the FROM clause as a relational expression. Można użyć podzapytania skalarnego jako wyrażenia skalarnego w klauzuli SELECT lub WHERE lub jako wyrażenie relacyjne w klauzuli FROM.You can use a scalar subquery as a scalar expression in the SELECT or WHERE clause, or as a relational expression in the FROM clause.

Podzapytania wielowartościoweMulti-value subqueries

Podzapytania o wiele wartości zwracają zestaw dokumentów i są zawsze używane w klauzuli FROM.Multi-value subqueries return a set of documents and are always used within the FROM clause. Są one używane do:They're used for:

  • Optymalizowanie wyrażeń SPRZĘŻENIa.Optimizing JOIN expressions.
  • Ocenianie kosztownych wyrażeń jednokrotnie i odwoływanie się do wielu razy.Evaluating expensive expressions once and referencing multiple times.

Optymalizuj wyrażenia SPRZĘŻENIaOptimize JOIN expressions

Podzapytania wielowartościowe mogą optymalizować wyrażenia SPRZĘŻENIa przez wypychanie predykatów po każdym wyrażeniu wyboru-wielu, a nie po wszystkich sprzężeniach krzyżowych w klauzuli WHERE.Multi-value subqueries can optimize JOIN expressions by pushing predicates after each select-many expression rather than after all cross-joins in the WHERE clause.

Rozpatrzmy następujące zapytanie:Consider the following query:

SELECT Count(1) AS Count
FROM c
JOIN t IN c.tags
JOIN n IN c.nutrients
JOIN s IN c.servings
WHERE t.name = 'infant formula' AND (n.nutritionValue > 0 
AND n.nutritionValue < 10) AND s.amount > 1

Dla tego zapytania indeks będzie pasować do dowolnego dokumentu, który ma tag o nazwie "Formuła niemowląt".For this query, the index will match any document that has a tag with the name "infant formula." Jest to element składnika pokarmowego z wartością z przedziału od 0 do 10 i obsługujący element o wartości większej niż 1.It's a nutrient item with a value between 0 and 10, and a serving item with an amount greater than 1. Wyrażenie JOIN w tym miejscu będzie przekroczyć iloczyn wszystkich elementów tagów, składników odżywczych i obsługuje tablice dla każdego pasującego dokumentu przed zastosowaniem filtra.The JOIN expression here will perform the cross-product of all items of tags, nutrients, and servings arrays for each matching document before any filter is applied.

Klauzula WHERE następnie zastosuje predykat filtru dla każdej <, t, n, s> krotki.The WHERE clause will then apply the filter predicate on each <c, t, n, s> tuple. Na przykład, jeśli pasujący dokument ma 10 elementów w każdej z trzech tablic, zostanie rozszerzony na 1 x 10 x 10 x 10 (czyli 1 000) krotek.For instance, if a matching document had 10 items in each of the three arrays, it will expand to 1 x 10 x 10 x 10 (that is, 1,000) tuples. Użycie podkwerend tutaj może pomóc w filtrowaniu sprzężonych elementów tablicy przed dołączeniem do następnego wyrażenia.Using subqueries here can help in filtering out joined array items before joining with the next expression.

To zapytanie jest równoważne poprzedniemu, ale używa podzapytań:This query is equivalent to the preceding one but uses subqueries:

SELECT Count(1) AS Count
FROM c
JOIN (SELECT VALUE t FROM t IN c.tags WHERE t.name = 'infant formula')
JOIN (SELECT VALUE n FROM n IN c.nutrients WHERE n.nutritionValue > 0 AND n.nutritionValue < 10)
JOIN (SELECT VALUE s FROM s IN c.servings WHERE s.amount > 1)

Załóżmy, że tylko jeden element w tablicy tagów pasuje do filtru i istnieje pięć elementów dla obydwu składników pokarmowych i obsługujących tablice.Assume that only one item in the tags array matches the filter, and there are five items for both nutrients and servings arrays. Wyrażenia SPRZĘŻENIa zostaną następnie rozszerzone na 1 x 1 x 5 x 5 = 25 elementów, w przeciwieństwie do 1 000 elementów w pierwszej kwerendzie.The JOIN expressions will then expand to 1 x 1 x 5 x 5 = 25 items, as opposed to 1,000 items in the first query.

Oceń raz i odwołuje się wiele razyEvaluate once and reference many times

Podzapytania mogą pomóc zoptymalizować zapytania z kosztownymi wyrażeniami, takimi jak funkcje zdefiniowane przez użytkownika (UDF), ciągi złożone lub wyrażenia arytmetyczne.Subqueries can help optimize queries with expensive expressions such as user-defined functions (UDFs), complex strings, or arithmetic expressions. Możesz użyć podzapytania wraz z wyrażeniem SPRZĘŻENIa, aby obliczyć wyrażenie jeden raz, ale odwołują się do niego wiele razy.You can use a subquery along with a JOIN expression to evaluate the expression once but reference it many times.

Następujące zapytanie uruchamia GetMaxNutritionValue dwa razy klawisz UDF:The following query runs the UDF GetMaxNutritionValue twice:

SELECT c.id, udf.GetMaxNutritionValue(c.nutrients) AS MaxNutritionValue
FROM c
WHERE udf.GetMaxNutritionValue(c.nutrients) > 100

Oto odpowiednik zapytania, które uruchamia tylko jeden raz:Here's an equivalent query that runs the UDF only once:

SELECT TOP 1000 c.id, MaxNutritionValue
FROM c
JOIN (SELECT VALUE udf.GetMaxNutritionValue(c.nutrients)) MaxNutritionValue
WHERE MaxNutritionValue > 100

Uwaga

Należy zwrócić uwagę na zachowanie różnych produktów w wyrażeniach SPRZĘŻENIa.Keep in mind the cross-product behavior of JOIN expressions. Jeśli wyrażenie UDF może oszacować do wartości undefined, należy upewnić się, że wyrażenie JOIN zawsze generuje pojedynczy wiersz, zwracając obiekt z podzapytania, a nie wartość bezpośrednio.If the UDF expression can evaluate to undefined, you should ensure that the JOIN expression always produces a single row by returning an object from the subquery rather than the value directly.

Oto podobny przykład, który zwraca obiekt, a nie wartość:Here's a similar example that returns an object rather than a value:

SELECT TOP 1000 c.id, m.MaxNutritionValue
FROM c
JOIN (SELECT udf.GetMaxNutritionValue(c.nutrients) AS MaxNutritionValue) m
WHERE m.MaxNutritionValue > 100

Podejście nie jest ograniczone do UDF.The approach is not limited to UDFs. Ma to zastosowanie do dowolnego potencjalnego wyrażenia.It applies to any potentially expensive expression. Na przykład można zastosować takie samo podejście z funkcją matematyczną avg :For example, you can take the same approach with the mathematical function avg:

SELECT TOP 1000 c.id, AvgNutritionValue
FROM c
JOIN (SELECT VALUE avg(n.nutritionValue) FROM n IN c.nutrients) AvgNutritionValue
WHERE AvgNutritionValue > 80

Naśladowanie sprzężenia z zewnętrznymi danymi referencyjnymiMimic join with external reference data

Czasami może być konieczne odwołujące się do danych statycznych, które rzadko zmieniają się, na przykład jednostek miary lub kodów krajów.You might often need to reference static data that rarely changes, such as units of measurement or country codes. Lepiej nie duplikować takich danych dla każdego dokumentu.It’s better not to duplicate such data for each document. Uniknięcie tego duplikacji spowoduje zapisanie w magazynie i zwiększenie wydajności zapisu przez pozostawienie mniejszego rozmiaru dokumentu.Avoiding this duplication will save on storage and improve write performance by keeping the document size smaller. Za pomocą podzapytania można naśladować semantykę sprzężenia wewnętrznego z kolekcją danych referencyjnych.You can use a subquery to mimic inner-join semantics with a collection of reference data.

Na przykład rozważmy ten zestaw danych referencyjnych:For instance, consider this set of reference data:

JednostkaUnit NazwaName MnożnikMultiplier Jednostka podstawowaBase unit
gazung NanogramNanogram 1.00 e-091.00E-09 SprawdzanieGram
gµg MicrogramMicrogram 1.00 e-061.00E-06 SprawdzanieGram
mgmg IlośćMilligram 1,00 e-031.00E-03 SprawdzanieGram
gg SprawdzanieGram 1,00 e + 001.00E+00 SprawdzanieGram
kilogramkg KgKilogram 1,00 e + 031.00E+03 SprawdzanieGram
MgMg MegagramMegagram 1,00 e + 061.00E+06 SprawdzanieGram
GGGg GigagramGigagram 1,00 e + 091.00E+09 SprawdzanieGram
nJnJ NanojouleNanojoule 1.00 e-091.00E-09 Joule —Joule
µJµJ MicrojouleMicrojoule 1.00 e-061.00E-06 Joule —Joule
mJmJ MillijouleMillijoule 1,00 e-031.00E-03 Joule —Joule
JJ Joule —Joule 1,00 e + 001.00E+00 Joule —Joule
Programu kJkJ KilojouleKilojoule 1,00 e + 031.00E+03 Joule —Joule
MJMJ MegajouleMegajoule 1,00 e + 061.00E+06 Joule —Joule
GJGJ GigajouleGigajoule 1,00 e + 091.00E+09 Joule —Joule
calcal CalorieCalorie 1,00 e + 001.00E+00 caloriecalorie
kcalkcal CalorieCalorie 1,00 e + 031.00E+03 caloriecalorie
IUIU Jednostki międzynarodoweInternational units

Następujące zapytanie naśladuje sprzężenie z tymi danymi, aby dodać nazwę jednostki do danych wyjściowych:The following query mimics joining with this data so that you add the name of the unit to the output:

SELECT TOP 10 n.id, n.description, n.nutritionValue, n.units, r.name
FROM food
JOIN n IN food.nutrients
JOIN r IN (
    SELECT VALUE [
        {unit: 'ng', name: 'nanogram', multiplier: 0.000000001, baseUnit: 'gram'},
        {unit: 'µg', name: 'microgram', multiplier: 0.000001, baseUnit: 'gram'},
        {unit: 'mg', name: 'milligram', multiplier: 0.001, baseUnit: 'gram'},
        {unit: 'g', name: 'gram', multiplier: 1, baseUnit: 'gram'},
        {unit: 'kg', name: 'kilogram', multiplier: 1000, baseUnit: 'gram'},
        {unit: 'Mg', name: 'megagram', multiplier: 1000000, baseUnit: 'gram'},
        {unit: 'Gg', name: 'gigagram', multiplier: 1000000000, baseUnit: 'gram'},
        {unit: 'nJ', name: 'nanojoule', multiplier: 0.000000001, baseUnit: 'joule'},
        {unit: 'µJ', name: 'microjoule', multiplier: 0.000001, baseUnit: 'joule'},
        {unit: 'mJ', name: 'millijoule', multiplier: 0.001, baseUnit: 'joule'},
        {unit: 'J', name: 'joule', multiplier: 1, baseUnit: 'joule'},
        {unit: 'kJ', name: 'kilojoule', multiplier: 1000, baseUnit: 'joule'},
        {unit: 'MJ', name: 'megajoule', multiplier: 1000000, baseUnit: 'joule'},
        {unit: 'GJ', name: 'gigajoule', multiplier: 1000000000, baseUnit: 'joule'},
        {unit: 'cal', name: 'calorie', multiplier: 1, baseUnit: 'calorie'},
        {unit: 'kcal', name: 'Calorie', multiplier: 1000, baseUnit: 'calorie'},
        {unit: 'IU', name: 'International units'}
    ]
)
WHERE n.units = r.unit

Podzapytania skalarneScalar subqueries

Skalarne wyrażenie podzapytania jest podzapytaniem, którego wynikiem jest pojedyncza wartość.A scalar subquery expression is a subquery that evaluates to a single value. Wartość wyrażenia skalarnego podzapytania jest wartością projekcji (klauzula SELECT) podzapytania.The value of the scalar subquery expression is the value of the projection (SELECT clause) of the subquery. Wyrażenia skalarnego podzapytania można użyć w wielu miejscach, w których wyrażenie skalarne jest prawidłowe.You can use a scalar subquery expression in many places where a scalar expression is valid. Można na przykład użyć podzapytania skalarnego w dowolnym wyrażeniu w klauzuli SELECT i WHERE.For instance, you can use a scalar subquery in any expression in both the SELECT and WHERE clauses.

Użycie podzapytania skalarnego nie zawsze pomaga zoptymalizować, chociaż.Using a scalar subquery doesn't always help optimize, though. Na przykład przekazywanie podzapytania skalarnego jako argumentu do systemu lub funkcji zdefiniowanych przez użytkownika nie zapewnia żadnej korzyści dotyczącej użycia jednostki zasobów (RU) ani opóźnienia.For example, passing a scalar subquery as an argument to either a system or user-defined functions provides no benefit in resource unit (RU) consumption or latency.

Podzapytania skalarne mogą być klasyfikowane jako:Scalar subqueries can be further classified as:

  • Podzapytania skalarne w wyrażeniach prostychSimple-expression scalar subqueries
  • Agreguj podzapytania skalarneAggregate scalar subqueries

Podzapytania skalarne w wyrażeniach prostychSimple-expression scalar subqueries

Uproszczone podzapytanie skalarne wyrażeń jest skorelowane podzapytanie, które ma klauzulę SELECT, która nie zawiera żadnych wyrażeń agregujących.A simple-expression scalar subquery is a correlated subquery that has a SELECT clause that doesn't contain any aggregate expressions. Te podzapytania nie zapewniają korzyści optymalizacji, ponieważ kompilator konwertuje je na jedno większe wyrażenie proste.These subqueries provide no optimization benefits because the compiler converts them into one larger simple expression. Nie istnieje skorelowany kontekst między zapytaniami wewnętrznymi i zewnętrznymi.There's no correlated context between the inner and outer queries.

Oto kilka przykładów:Here are few examples:

Przykład 1Example 1

SELECT 1 AS a, 2 AS b

Możesz ponownie napisać to zapytanie, używając prostego podzapytania skalarnego Expression, aby:You can rewrite this query, by using a simple-expression scalar subquery, to:

SELECT (SELECT VALUE 1) AS a, (SELECT VALUE 2) AS b

Oba zapytania tworzą następujące dane wyjściowe:Both queries produce this output:

[
  { "a": 1, "b": 2 }
]

Przykład 2Example 2

SELECT TOP 5 Concat('id_', f.id) AS id
FROM food f

Możesz ponownie napisać to zapytanie, używając prostego podzapytania skalarnego Expression, aby:You can rewrite this query, by using a simple-expression scalar subquery, to:

SELECT TOP 5 (SELECT VALUE Concat('id_', f.id)) AS id
FROM food f

Wyniki zapytania:Query output:

[
  { "id": "id_03226" },
  { "id": "id_03227" },
  { "id": "id_03228" },
  { "id": "id_03229" },
  { "id": "id_03230" }
]

Przykład 3Example 3

SELECT TOP 5 f.id, Contains(f.description, 'fruit') = true ? f.description : undefined
FROM food f

Możesz ponownie napisać to zapytanie, używając prostego podzapytania skalarnego Expression, aby:You can rewrite this query, by using a simple-expression scalar subquery, to:

SELECT TOP 10 f.id, (SELECT f.description WHERE Contains(f.description, 'fruit')).description
FROM food f

Wyniki zapytania:Query output:

[
  { "id": "03230" },
  { "id": "03238", "description":"Babyfood, dessert, tropical fruit, junior" },
  { "id": "03229" },
  { "id": "03226", "description":"Babyfood, dessert, fruit pudding, orange, strained" },
  { "id": "03227" }
]

Agreguj podzapytania skalarneAggregate scalar subqueries

Zagregowane podzapytanie skalarne jest podzapytaniem, które zawiera funkcję agregującą w projekcji lub filtr, który daje w wyniku pojedynczą wartość.An aggregate scalar subquery is a subquery that has an aggregate function in its projection or filter that evaluates to a single value.

Przykład 1:Example 1:

Oto podzapytanie zawierające wyrażenie pojedynczego funkcji agregującej w projekcji:Here's a subquery with a single aggregate function expression in its projection:

SELECT TOP 5 
    f.id, 
    (SELECT VALUE Count(1) FROM n IN f.nutrients WHERE n.units = 'mg'
) AS count_mg
FROM food f

Wyniki zapytania:Query output:

[
  { "id": "03230", "count_mg": 13 },
  { "id": "03238", "count_mg": 14 },
  { "id": "03229", "count_mg": 13 },
  { "id": "03226", "count_mg": 15 },
  { "id": "03227", "count_mg": 19 }
]

Przykład 2Example 2

Oto podzapytanie z wieloma wyrażeniami funkcji agregowania:Here's a subquery with multiple aggregate function expressions:

SELECT TOP 5 f.id, (
    SELECT Count(1) AS count, Sum(n.nutritionValue) AS sum 
    FROM n IN f.nutrients 
    WHERE n.units = 'mg'
) AS unit_mg
FROM food f

Wyniki zapytania:Query output:

[
  { "id": "03230","unit_mg": { "count": 13,"sum": 147.072 } },
  { "id": "03238","unit_mg": { "count": 14,"sum": 107.385 } },
  { "id": "03229","unit_mg": { "count": 13,"sum": 141.579 } },
  { "id": "03226","unit_mg": { "count": 15,"sum": 183.91399999999996 } },
  { "id": "03227","unit_mg": { "count": 19,"sum": 94.788999999999987 } }
]

Przykład 3Example 3

Oto zapytanie z podzapytaniem zagregowanym zarówno dla projekcji, jak i filtru:Here's a query with an aggregate subquery in both the projection and the filter:

SELECT TOP 5 
    f.id, 
    (SELECT VALUE Count(1) FROM n IN f.nutrients WHERE n.units = 'mg') AS count_mg
FROM food f
WHERE (SELECT VALUE Count(1) FROM n IN f.nutrients WHERE n.units = 'mg') > 20

Wyniki zapytania:Query output:

[
  { "id": "03235", "count_mg": 27 },
  { "id": "03246", "count_mg": 21 },
  { "id": "03267", "count_mg": 21 },
  { "id": "03269", "count_mg": 21 },
  { "id": "03274", "count_mg": 21 }
]

Bardziej optymalnym sposobem pisania tego zapytania jest dołączenie do podzapytania i odwołanie się do aliasu podzapytania w klauzulach SELECT i WHERE.A more optimal way to write this query is to join on the subquery and reference the subquery alias in both the SELECT and WHERE clauses. To zapytanie jest bardziej wydajne, ponieważ należy wykonać podzapytanie tylko w instrukcji join, a nie w projekcji i filtrze.This query is more efficient because you need to execute the subquery only within the join statement, and not in both the projection and filter.

SELECT TOP 5 f.id, count_mg
FROM food f
JOIN (SELECT VALUE Count(1) FROM n IN f.nutrients WHERE n.units = 'mg') AS count_mg
WHERE count_mg > 20

Wyrażenie EXISTSEXISTS expression

Azure Cosmos DB obsługuje wyrażenia EXISTS.Azure Cosmos DB supports EXISTS expressions. Jest to zagregowane podzapytanie skalarne wbudowane w interfejs API SQL Azure Cosmos DB.This is an aggregate scalar subquery built into the Azure Cosmos DB SQL API. EXISTS jest wyrażeniem logicznym, które przyjmuje wyrażenie subquery i zwraca wartość true, jeśli podzapytanie zwraca wszystkie wiersze.EXISTS is a Boolean expression that takes a subquery expression and returns true if the subquery returns any rows. W przeciwnym razie zwraca wartość false.Otherwise, it returns false.

Ponieważ Azure Cosmos DB interfejs API SQL nie rozróżnia wyrażeń logicznych i innych wyrażeń skalarnych, można użyć operatora EXISTS w obu klauzulach SELECT i WHERE.Because the Azure Cosmos DB SQL API doesn't differentiate between Boolean expressions and any other scalar expressions, you can use EXISTS in both SELECT and WHERE clauses. Jest to w przeciwieństwie do języka T-SQL, gdzie wyrażenie logiczne (na przykład istnieje, między i w) jest ograniczone do filtru.This is unlike T-SQL, where a Boolean expression (for example, EXISTS, BETWEEN, and IN) is restricted to the filter.

Jeśli podzapytanie EXISTS zwróci pojedynczą wartość, która nie jest zdefiniowana, istnieje wartość false.If the EXISTS subquery returns a single value that's undefined, EXISTS will evaluate to false. Na przykład rozważmy następujące zapytanie, którego wynikiem jest wartość false:For instance, consider the following query that evaluates to false:

SELECT EXISTS (SELECT VALUE undefined)

Jeśli słowo kluczowe VALUE w powyższym podzapytaniu zostanie pominięte, kwerenda zwróci wartość true:If the VALUE keyword in the preceding subquery is omitted, the query will evaluate to true:

SELECT EXISTS (SELECT undefined) 

Podzapytanie będzie zawierać listę wartości z wybranej listy w obiekcie.The subquery will enclose the list of values in the selected list in an object. Jeśli wybrana lista nie ma żadnych wartości, podzapytanie zwróci pojedynczą wartość " {} ".If the selected list has no values, the subquery will return the single value ‘{}’. Ta wartość jest zdefiniowana, a zatem istnieje wartość true.This value is defined, so EXISTS evaluates to true.

Przykład: zapisywanie ARRAY_CONTAINS i dołączanie jako istniejeExample: Rewriting ARRAY_CONTAINS and JOIN as EXISTS

Typowym przypadkiem użycia ARRAY_CONTAINS jest filtrowanie dokumentu przez istnienie elementu w tablicy.A common use case of ARRAY_CONTAINS is to filter a document by the existence of an item in an array. W tym przypadku Sprawdzamy, czy tablica tagów zawiera element o nazwie "pomarańczowy".In this case, we're checking to see if the tags array contains an item named "orange."

SELECT TOP 5 f.id, f.tags
FROM food f
WHERE ARRAY_CONTAINS(f.tags, {name: 'orange'})

Możesz ponownie napisać to samo zapytanie do użycia:You can rewrite the same query to use EXISTS:

SELECT TOP 5 f.id, f.tags
FROM food f
WHERE EXISTS(SELECT VALUE t FROM t IN f.tags WHERE t.name = 'orange')

Ponadto ARRAY_CONTAINS można sprawdzić tylko wtedy, gdy wartość jest równa każdemu elementowi w tablicy.Additionally, ARRAY_CONTAINS can only check if a value is equal to any element within an array. Jeśli potrzebujesz bardziej złożonych filtrów dla właściwości tablicy, użyj SPRZĘŻENIa.If you need more complex filters on array properties, use JOIN.

Rozważmy następujące zapytanie, które jest oparte na jednostkach i nutritionValue właściwościach tablicy:Consider the following query that filters based on the units and nutritionValue properties in the array:

SELECT VALUE c.description
FROM c
JOIN n IN c.nutrients
WHERE n.units= "mg" AND n.nutritionValue > 0

Dla każdego dokumentu w kolekcji, wiele produktów jest wykonywanych ze swoimi elementami tablicy.For each of the documents in the collection, a cross-product is performed with its array elements. Ta operacja łączenia umożliwia filtrowanie właściwości w tablicy.This JOIN operation makes it possible to filter on properties within the array. Użycie tego zapytania jest jednak istotne.However, this query’s RU consumption will be significant. Na przykład jeśli 1 000 dokumenty mają 100 elementy w każdej tablicy, zostanie rozwinięte do 1 000 x 100 (czyli 100 000) krotek.For instance, if 1,000 documents had 100 items in each array, it will expand to 1,000 x 100 (that is, 100,000) tuples.

Użycie już istnieje może pomóc w uniknięciu tego kosztownego skrzyżowania:Using EXISTS can help to avoid this expensive cross-product:

SELECT VALUE c.description
FROM c
WHERE EXISTS(
    SELECT VALUE n
    FROM n IN c.nutrients
    WHERE n.units = "mg" AND n.nutritionValue > 0
)

W takim przypadku należy odfiltrować elementy tablicy w podzapytaniu EXISTS.In this case, you filter on array elements within the EXISTS subquery. Jeśli element tablicy jest zgodny z filtrem, należy go projektować i istnieje wartość true.If an array element matches the filter, then you project it and EXISTS evaluates to true.

Istnieje również możliwość aliasowania i odwoływania się do niego w projekcji:You can also alias EXISTS and reference it in the projection:

SELECT TOP 1 c.description, EXISTS(
    SELECT VALUE n
    FROM n IN c.nutrients
    WHERE n.units = "mg" AND n.nutritionValue > 0) as a
FROM c

Wyniki zapytania:Query output:

[
    {
        "description": "Babyfood, dessert, fruit pudding, orange, strained",
        "a": true
    }
]

Wyrażenie tablicyARRAY expression

Możesz użyć wyrażenia ARRAY, aby zaprojektować wyniki zapytania jako tablicę.You can use the ARRAY expression to project the results of a query as an array. Tego wyrażenia można użyć tylko w klauzuli SELECT zapytania.You can use this expression only within the SELECT clause of the query.

SELECT TOP 1   f.id, ARRAY(SELECT VALUE t.name FROM t in f.tags) AS tagNames
FROM  food f

Wyniki zapytania:Query output:

[
    {
        "id": "03238",
        "tagNames": [
            "babyfood",
            "dessert",
            "tropical fruit",
            "junior"
        ]
    }
]

Podobnie jak w przypadku innych podkwerend, filtry z wyrażeniem ARRAY są możliwe.As with other subqueries, filters with the ARRAY expression are possible.

SELECT TOP 1 c.id, ARRAY(SELECT VALUE t FROM t in c.tags WHERE t.name != 'infant formula') AS tagNames
FROM c

Wyniki zapytania:Query output:

[
    {
        "id": "03226",
        "tagNames": [
            {
                "name": "babyfood"
            },
            {
                "name": "dessert"
            },
            {
                "name": "fruit pudding"
            },
            {
                "name": "orange"
            },
            {
                "name": "strained"
            }
        ]
    }
]

Wyrażenia tablicowe mogą być również dostępne po klauzuli FROM w podzapytaniach.Array expressions can also come after the FROM clause in subqueries.

SELECT TOP 1 c.id, ARRAY(SELECT VALUE t.name FROM t in c.tags) as tagNames
FROM c
JOIN n IN (SELECT VALUE ARRAY(SELECT t FROM t in c.tags WHERE t.name != 'infant formula'))

Wyniki zapytania:Query output:

[
    {
        "id": "03238",
        "tagNames": [
            "babyfood",
            "dessert",
            "tropical fruit",
            "junior"
        ]
    }
]

Następne krokiNext steps