Klauzule FROM plus JOIN, APPLY, PIVOT (Transact-SQL)
platí pro: SQL Server 2016 (13.x) a novější verze Azure SQL DatabaseAzure SQL Managed InstanceAzure Synapse AnalyticsAnalytics Platform System (PDW)koncový bod analýzy SQL v Microsoft FabricWarehouse v databázi Microsoft FabricSQL v Microsoft Fabric
V jazyce Transact-SQL je klauzule FROM k dispozici v následujících příkazech:
Klauzule FROM se obvykle vyžaduje u příkazu SELECT. Výjimkou je, že nejsou uvedeny žádné sloupce tabulky a jedinými uvedenými položkami jsou literály nebo proměnné nebo aritmetické výrazy.
Tento článek také popisuje následující klíčová slova, která lze použít v klauzuli FROM:
- JOIN
- POUŽÍT
- KONTINGENČNÍ
Syntax
Syntaxe pro SQL Server, Azure SQL Database a databázi SQL Fabric:
[ FROM { <table_source> } [ , ...n ] ]
<table_source> ::=
{
table_or_view_name [ FOR SYSTEM_TIME <system_time> ] [ [ AS ] table_alias ]
[ <tablesample_clause> ]
[ WITH ( < table_hint > [ [ , ] ...n ] ) ]
| rowset_function [ [ AS ] table_alias ]
[ ( bulk_column_alias [ , ...n ] ) ]
| user_defined_function [ [ AS ] table_alias ]
| OPENXML <openxml_clause>
| derived_table [ [ AS ] table_alias ] [ ( column_alias [ , ...n ] ) ]
| <joined_table>
| <pivoted_table>
| <unpivoted_table>
| @variable [ [ AS ] table_alias ]
| @variable.function_call ( expression [ , ...n ] )
[ [ AS ] table_alias ] [ (column_alias [ , ...n ] ) ]
}
<tablesample_clause> ::=
TABLESAMPLE [ SYSTEM ] ( sample_number [ PERCENT | ROWS ] )
[ REPEATABLE ( repeat_seed ) ]
<joined_table> ::=
{
<table_source> <join_type> <table_source> ON <search_condition>
| <table_source> CROSS JOIN <table_source>
| left_table_source { CROSS | OUTER } APPLY right_table_source
| [ ( ] <joined_table> [ ) ]
}
<join_type> ::=
[ { INNER | { { LEFT | RIGHT | FULL } [ OUTER ] } } [ <join_hint> ] ]
JOIN
<pivoted_table> ::=
table_source PIVOT <pivot_clause> [ [ AS ] table_alias ]
<pivot_clause> ::=
( aggregate_function ( value_column [ [ , ] ...n ] )
FOR pivot_column
IN ( <column_list> )
)
<unpivoted_table> ::=
table_source UNPIVOT <unpivot_clause> [ [ AS ] table_alias ]
<unpivot_clause> ::=
( value_column FOR pivot_column IN ( <column_list> ) )
<column_list> ::=
column_name [ , ...n ]
<system_time> ::=
{
AS OF <date_time>
| FROM <start_date_time> TO <end_date_time>
| BETWEEN <start_date_time> AND <end_date_time>
| CONTAINED IN (<start_date_time> , <end_date_time>)
| ALL
}
<date_time>::=
<date_time_literal> | @date_time_variable
<start_date_time>::=
<date_time_literal> | @date_time_variable
<end_date_time>::=
<date_time_literal> | @date_time_variable
Syntaxe paralelního datového skladu, Azure Synapse Analytics:
FROM { <table_source> [ , ...n ] }
<table_source> ::=
{
[ database_name . [ schema_name ] . | schema_name . ] table_or_view_name [ AS ] table_or_view_alias
[ <tablesample_clause> ]
| derived_table [ AS ] table_alias [ ( column_alias [ , ...n ] ) ]
| <joined_table>
}
<tablesample_clause> ::=
TABLESAMPLE ( sample_number [ PERCENT ] ) -- Azure Synapse Analytics Dedicated SQL pool only
<joined_table> ::=
{
<table_source> <join_type> <table_source> ON search_condition
| <table_source> CROSS JOIN <table_source>
| left_table_source { CROSS | OUTER } APPLY right_table_source
| [ ( ] <joined_table> [ ) ]
}
<join_type> ::=
[ INNER ] [ <join hint> ] JOIN
| LEFT [ OUTER ] JOIN
| RIGHT [ OUTER ] JOIN
| FULL [ OUTER ] JOIN
<join_hint> ::=
REDUCE
| REPLICATE
| REDISTRIBUTE
Syntaxe pro Microsoft Fabric:
FROM { <table_source> [ , ...n ] }
<table_source> ::=
{
[ database_name . [ schema_name ] . | schema_name . ] table_or_view_name [ AS ] table_or_view_alias
| derived_table [ AS ] table_alias [ ( column_alias [ , ...n ] ) ]
| <joined_table>
}
<joined_table> ::=
{
<table_source> <join_type> <table_source> ON search_condition
| <table_source> CROSS JOIN <table_source>
| left_table_source { CROSS | OUTER } APPLY right_table_source
| [ ( ] <joined_table> [ ) ]
}
<join_type> ::=
[ INNER ] [ <join hint> ] JOIN
| LEFT [ OUTER ] JOIN
| RIGHT [ OUTER ] JOIN
| FULL [ OUTER ] JOIN
<join_hint> ::=
REDUCE
| REPLICATE
| REDISTRIBUTE
Argumenty
<table_source>
Určuje tabulku, zobrazení, proměnnou tabulky nebo odvozený zdroj tabulky s aliasem nebo bez něj, která se má použít v příkazu Transact-SQL. V příkazu lze použít až 256 zdrojů tabulek, i když se limit liší v závislosti na dostupné paměti a složitosti jiných výrazů v dotazu. Jednotlivé dotazy nemusí podporovat až 256 zdrojů tabulek.
Poznámka
Výkon dotazů může mít velké množství tabulek odkazovaných v dotazu. Čas kompilace a optimalizace jsou ovlivněny také dalšími faktory. Patří mezi ně přítomnost indexů a indexovaných zobrazení na jednotlivých <table_source> a velikost <select_list> v příkazu SELECT.
Pořadí zdrojů tabulky po klíčovém slovu FROM nemá vliv na vrácenou sadu výsledků. SQL Server vrátí chyby, když se v klauzuli FROM zobrazí duplicitní názvy.
table_or_view_name
Název tabulky nebo zobrazení.
Pokud tabulka nebo zobrazení existuje v jiné databázi na stejné instanci SQL Serveru, použijte plně kvalifikovaný název ve formuláři databáze.schématu.object_name.
Pokud tabulka nebo zobrazení existuje mimo instanci SYSTÉMU SQL Serverl, použijte ve formuláři
[AS] table_alias
Alias pro table_source, který lze použít pro usnadnění nebo rozlišení tabulky nebo zobrazení v poddotazovém spojení nebo poddotazu. Alias je často zkrácený název tabulky, který slouží k odkazování na konkrétní sloupce tabulek ve spojení. Pokud stejný název sloupce existuje ve spojení ve více než jedné tabulce, SQL Server může vyžadovat, aby byl název sloupce kvalifikovaný názvem tabulky, názvem zobrazení nebo aliasem k rozlišení těchto sloupců. Název tabulky nelze použít, pokud je definován alias.
Pokud se použije odvozená tabulka, sada řádků nebo funkce s hodnotou tabulky nebo klauzule operátoru (například PIVOT nebo UNPIVOT), vrátí se požadovaný table_alias na konci klauzule název přidružené tabulky pro všechny sloupce, včetně seskupování sloupců.
WITH (<table_hint> )
Určuje, že optimalizátor dotazů používá strategii optimalizace nebo uzamčení s touto tabulkou a pro tento příkaz. Další informace naleznete v tématu Nápovědy k tabulce (Transact-SQL).
rowset_function
platí pro: SQL Server a SQL Database.
Určuje jednu z funkcí sady řádků, například OPENROWSET, která vrací objekt, který lze použít místo odkazu na tabulku. Další informace o seznamu funkcí sady řádků naleznete v tématu Funkce sady řádků (Transact-SQL).
Použití funkcí OPENROWSET a OPENQUERY k určení vzdáleného objektu závisí na schopnostech zprostředkovatele OLE DB, který přistupuje k objektu.
bulk_column_alias
platí pro: SQL Server a SQL Database.
Volitelný alias pro nahrazení názvu sloupce v sadě výsledků. Aliasy sloupců jsou povoleny pouze v příkazech SELECT, které používají funkci OPENROWSET s možností BULK. Při použití bulk_column_aliaszadejte alias pro každý sloupec tabulky ve stejném pořadí jako sloupce v souboru.
Poznámka
Tento alias přepíše atribut NAME v elementech COLUMN souboru formátu XML, pokud je k dispozici.
user_defined_function
Určuje funkci s hodnotou tabulky.
<openxml_clause> OPENXML
platí pro: SQL Server a SQL Database.
Poskytuje zobrazení sady řádků v dokumentu XML. Další informace najdete v tématu
derived_table
Poddotaz, který načte řádky z databáze. derived_table slouží jako vstup pro vnější dotaz.
derived_table může pomocí funkce konstruktoru hodnot tabulky Transact-SQL zadat více řádků. Například SELECT * FROM (VALUES (1, 2), (3, 4), (5, 6), (7, 8), (9, 10) ) AS MyTable(a, b);
. Další informace naleznete v tématu Konstruktor hodnot tabulky (Transact-SQL).
column_alias
Volitelný alias pro nahrazení názvu sloupce v sadě výsledků odvozené tabulky. Zahrňte jeden alias sloupce pro každý sloupec v seznamu výběru a uzavřete úplný seznam aliasů sloupců do závorek.
table_or_view_name FOR SYSTEM_TIME <system_time>
platí pro: SQL Server 2016 (13.x) a novější verze a SQL Database.
Určuje, že konkrétní verze dat se vrátí ze zadané dočasné tabulky a z propojené tabulky historie verzí systému.
Klauzule TABLESAMPLE
platí pro: SQL Server, SQL Database a vyhrazené fondy SQL služby Azure Synapse Analytics
Určuje, že se vrátí ukázka dat z tabulky. Ukázka může být přibližná. Tuto klauzuli lze použít u jakékoli primární nebo spojené tabulky v příkazu SELECT nebo UPDATE. U zobrazení nelze zadat TABLESAMPLE.
Poznámka
Při použití TABLESAMPLE pro databáze, které jsou upgradovány na SQL Server, je úroveň kompatibility databáze nastavena na 110 nebo vyšší, PIVOT není povolen v rekurzivním dotazu CTE (Common Table Expression). Další informace naleznete v tématu ÚROVEŇ kompatibility ALTER DATABASE (Transact-SQL).
SYSTÉM
Metoda vzorkování závislá na implementaci určená standardy ISO. V SQL Serveru je to jediná dostupná metoda vzorkování a ve výchozím nastavení se používá. SYSTEM použije metodu vzorkování založenou na stránce, ve které je pro vzorek vybrána náhodná sada stránek z tabulky a všechny řádky na těchto stránkách se vrátí jako ukázková podmnožina.
sample_number
Přesný nebo přibližný číselný výraz, který představuje procento nebo počet řádků. Při zadání pomocí funkce PERCENT se sample_number implicitně převede na hodnotu float; jinak se převede na bigint. Procento je výchozí hodnota.
PROCENTO
Určuje, že sample_number procento řádků tabulky by se mělo načíst z tabulky. Při zadání funkce PERCENT vrátí SQL Server přibližnou hodnotu zadaného procenta. Pokud je zadaná hodnota PERCENT, musí se výraz sample_number vyhodnotit na hodnotu od 0 do 100.
ŘÁDKY
Určuje, že se načtou přibližně sample_number řádků. Při zadání řádků vrátí SQL Server aproximaci zadaného počtu řádků. Pokud je zadána hodnota ROWS, výraz sample_number musí být vyhodnocen jako celočíselná hodnota větší než nula.
OPAKOVATELNÝ
Označuje, že vybranou ukázku je možné vrátit znovu. Pokud je zadána stejná hodnota repeat_seed, vrátí SQL Server stejnou podmnožinu řádků, pokud nebyly provedeny žádné změny v žádné řádky v tabulce. Pokud zadáte jinou repeat_seed hodnotu, SQL Server pravděpodobně vrátí nějaký jiný vzorek řádků v tabulce. Za změny v tabulce se považují následující akce: vložení, aktualizace, odstranění, opětovné sestavení indexu nebo defragmentace a obnovení databáze nebo připojení.
repeat_seed
Konstantní celočíselné výrazy používané SQL Serverem k vygenerování náhodného čísla. repeat_seed je bigint. Pokud není zadaný repeat_seed, SQL Server náhodně přiřadí hodnotu. U konkrétní repeat_seed hodnoty je výsledek vzorkování vždy stejný, pokud v tabulce nebyly použity žádné změny. Výraz repeat_seed musí být vyhodnocen jako celé číslo větší než nula.
Připojená tabulka
Spojená tabulka je sada výsledků, která je součinem dvou nebo více tabulek. U více spojení použijte závorky ke změně přirozeného pořadí spojení.
Typ spojení
Určuje typ operace spojení.
VNITŘNÍ
Určuje, že se vrátí všechny odpovídající dvojice řádků. Zahodí chybějící řádky z obou tabulek. Pokud není zadán žádný typ spojení, toto je výchozí hodnota.
PLNÁ [ VNĚJŠÍ ]
Určuje, že řádek z levé nebo pravé tabulky, která nesplňuje podmínku spojení, je součástí sady výsledků a výstupní sloupce, které odpovídají druhé tabulce, jsou nastaveny na hodnotu NULL. To je navíc ke všem řádkům, které obvykle vrací funkce INNER JOIN.
LEFT [ VNĚJŠÍ ]
Určuje, že všechny řádky z levé tabulky, které nesplňují podmínku spojení, jsou zahrnuty do sady výsledků a výstupní sloupce z druhé tabulky jsou kromě všech řádků vrácených vnitřním spojením nastaveny na hodnotu NULL.
RIGHT [ VNĚJŠÍ ]
Určuje všechny řádky z pravé tabulky, které nesplňují podmínku spojení, jsou zahrnuty do sady výsledků a výstupní sloupce, které odpovídají druhé tabulce, jsou kromě všech řádků vrácených vnitřním spojením nastaveny na hodnotu NULL.
Nápověda pro spojení
U SQL Serveru a služby SQL Database určuje, že optimalizátor dotazů SQL Serveru používá jeden tip spojení nebo algoritmus spouštění na spojení zadané v klauzuli FROM dotazu. Další informace naleznete v tématu Join Hints (Transact-SQL).
V případě systému Azure Synapse Analytics a Platform Platform System (PDW) se tyto rady spojení vztahují na vnitřní spojení ve dvou nekompatibilních sloupcích. Můžou zlepšit výkon dotazů omezením množství přesunu dat, ke kterému dochází během zpracování dotazů. Povolené tipy pro spojení pro Azure Synapse Analytics a PdW (Platform System) jsou následující:
ZMENŠIT
Zmenšuje počet řádků, které se mají přesunout pro tabulku na pravé straně spojení, aby byly dvě distribuce nekompatibilní tabulky kompatibilní. Tip REDUCE se také označuje jako tip pro střední spojení.
REPLIKOVAT
Způsobí replikaci hodnot ve sloupci spojení z tabulky na pravé straně spojení do všech uzlů. Tabulka vlevo je připojená k replikované verzi těchto sloupců.
PŘEROZDĚLIT
Vynutí rozdělení dvou zdrojů dat do sloupců zadaných v klauzuli JOIN. Pro distribuovanou tabulku provádí nástroj PdW (Analytics Platform System) přesun náhodného prohazování. U replikované tabulky provádí analýza systému PDW (Analytics Platform System) přesun oříznutí. Informace o těchto typech přesunů najdete v části "Operace plánu dotazů DMS" v článku "Principy plánů dotazů" v dokumentaci k produktu Analytics Platform System (PDW). Tento tip může zvýšit výkon, když plán dotazu používá přesun vysílání k vyřešení distribuce nekompatibilní spojení.
PŘIPOJIT
Označuje, že zadaná operace spojení by měla probíhat mezi zadanými zdroji tabulek nebo zobrazeními.
ZAPNUTO <search_condition>
Určuje podmínku, na které je spojení založeno. Podmínka může určit libovolný predikát, i když se často používají sloupce a relační operátory, například:
SELECT p.ProductID,
v.BusinessEntityID
FROM Production.Product AS p
INNER JOIN Purchasing.ProductVendor AS v
ON (p.ProductID = v.ProductID);
Pokud podmínka určuje sloupce, sloupce nemusí mít stejný název nebo stejný datový typ; Pokud však datové typy nejsou stejné, musí být kompatibilní nebo typy, které SQL Server může implicitně převést. Pokud datové typy nelze implicitně převést, podmínka musí datový typ explicitně převést pomocí funkce CONVERT.
Mohou existovat predikáty, které zahrnují pouze jednu z spojených tabulek v klauzuli ON. Takové predikáty mohou být také v klauzuli WHERE v dotazu. I když umístění takových predikátů neprovádí rozdíl pro vnitřní spojení, mohou způsobit jiný výsledek, když jsou zapojeny vnější spojení. Důvodem je to, že predikáty v klauzuli ON jsou použity na tabulku před spojením, zatímco klauzule WHERE je sémanticky použita na výsledek spojení.
Další informace o podmínkách hledání a predikátech najdete v tématu
KŘÍŽOVÉ SPOJENÍ
Určuje křížový součin dvou tabulek. Vrátí stejné řádky jako v případě, že nebyla zadána žádná klauzule WHERE ve starém stylu bez spojení typu SQL-92.
left_table_source { CROSS | VNĚJŠÍ } POUŽÍT right_table_source
Určuje, že right_table_source operátoru APPLY se vyhodnotí pro každý řádek left_table_source. Tato funkce je užitečná, když right_table_source obsahuje funkci s hodnotou tabulky, která přebírá hodnoty sloupců z left_table_source jako jeden z jejích argumentů.
Musí být zadána funkce CROSS nebo OUTER pomocí funkce APPLY. Při zadání funkce CROSS se při vyhodnocování right_table_source na zadaném řádku left_table_source nevygenerují žádné řádky a vrátí prázdnou sadu výsledků.
Při zadání funkce OUTER se pro každý řádek left_table_source vytvoří jeden řádek, i když right_table_source vyhodnotí tento řádek a vrátí prázdnou sadu výsledků.
Další informace najdete v části Poznámky.
left_table_source
Zdroj tabulky definovaný v předchozím argumentu Další informace najdete v části Poznámky.
right_table_source
Zdroj tabulky definovaný v předchozím argumentu Další informace najdete v části Poznámky.
Klauzule PIVOT
table_source KONTINGENČNÍ <pivot_clause>
Určuje, že table_source je kontingenční na základě pivot_column. table_source je výraz tabulky nebo tabulky. Výstup je tabulka, která obsahuje všechny sloupce table_source s výjimkou pivot_column a value_column. Sloupce table_sources výjimkou pivot_column a value_columnse nazývají sloupce seskupování kontingenčního operátoru. Další informace o funkci PIVOT a UNPIVOT naleznete v tématu Použití funkce PIVOT a FUNKCE UNPIVOT.
PIVOT provede operaci seskupení ve vstupní tabulce s ohledem na sloupce seskupení a vrátí jeden řádek pro každou skupinu. Výstup navíc obsahuje jeden sloupec pro každou hodnotu zadanou v column_list, která se zobrazí v pivot_columninput_table.
Další informace najdete v následujícím oddílu Poznámky.
aggregate_function
Systémová nebo uživatelem definovaná agregační funkce, která přijímá jeden nebo více vstupů. Agregační funkce by měla být invariantní na hodnoty null. Agregační funkce nebere v úvahu hodnoty null ve skupině při vyhodnocování agregační hodnoty.
Agregační funkce COUNT(*) není povolená.
value_column
Sloupec hodnoty operátoru PIVOT. Při použití s funkcemi UNPIVOT nemůže value_column být název existujícího sloupce ve vstupním table_source.
FOR pivot_column
Kontingenční sloupec operátoru PIVOT. pivot_column musí být typu implicitně nebo explicitně konvertibilní na nvarchar(). Tento sloupec nemůže být obrázku ani rowversion .
Při použití funkce UNPIVOT je pivot_column název výstupního sloupce, který se zužuje z table_source. V table_source s tímto názvem nemůže být existující sloupec.
IN ( column_list )
V klauzuli PIVOT se zobrazí hodnoty v pivot_column, které se stanou názvy sloupců výstupní tabulky. Seznam nemůže zadat žádné názvy sloupců, které již existují ve vstupním table_source, které jsou kontingenční.
V klauzuli UNPIVOT uvádí sloupce v table_source, které jsou zúženy na jeden pivot_column.
table_alias
Název aliasu výstupní tabulky pivot_table_alias je nutné zadat.
<UNPIVOT_CLAUSE> UNPIVOT
Určuje, že vstupní tabulka je zúžena z více sloupců v column_list do jednoho sloupce nazývaného pivot_column. Další informace o funkci PIVOT a UNPIVOT naleznete v tématu Použití funkce PIVOT a FUNKCE UNPIVOT.
OD <DATE_TIME>
platí pro: SQL Server 2016 (13.x) a novější verze a SQL Database.
Vrátí tabulku s jedním záznamem pro každý řádek obsahující hodnoty, které byly skutečné (aktuální) v zadaném bodu v čase v minulosti. Interně se provádí sjednocení mezi dočasnou tabulkou a její tabulkou historie a výsledky jsou filtrovány tak, aby vrátily hodnoty v řádku, které byly platné v okamžiku v čase určeném parametrem <date_time>. Hodnota řádku se považuje za platnou, pokud je hodnota system_start_time_column_name menší nebo rovna hodnotě parametru <date_time> a hodnota system_end_time_column_name je větší než hodnota parametru <date_time>.
FROM <start_date_time> to <end_date_time>
platí pro: SQL Server 2016 (13.x) a novější verze a SQL Database.
Vrátí tabulku s hodnotami pro všechny verze záznamů, které byly aktivní v zadaném časovém rozsahu, bez ohledu na to, zda začaly být aktivní před <start_date_time> hodnota parametru pro argument FROM nebo přestala být aktivní za hodnotou parametru <end_date_time> pro argument TO. Interně se provádí sjednocení mezi dočasnou tabulkou a její tabulkou historie a výsledky jsou filtrovány tak, aby vracely hodnoty pro všechny verze řádků, které byly aktivní kdykoli během zadaného časového rozsahu. Řádky, které se staly aktivní přesně na dolní hranici definované koncovým bodem FROM, jsou zahrnuty a řádky, které se staly aktivní přesně na horní hranici definované koncovým bodem TO, nejsou zahrnuty.
BETWEEN <start_date_time> AND <end_date_time>
platí pro: SQL Server 2016 (13.x) a novější verze a SQL Database.
Stejné jako výše v popisu FROM <start_date_time> TO <end_date_time> s výjimkou řádků, které se staly aktivními na horní hranici definované koncovým bodem <end_date_time>.
OBSAŽENÉ V (<start_date_time> , <end_date_time>)
platí pro: SQL Server 2016 (13.x) a novější verze a SQL Database.
Vrátí tabulku s hodnotami pro všechny verze záznamů, které byly otevřeny a uzavřeny v zadaném časovém rozsahu definovaném dvěma hodnotami data a času pro argument CONTAINED IN. Řádky, které byly aktivní přesně na dolní hranici nebo přestaly být aktivní přesně na horní hranici, jsou zahrnuty.
VŠICHNI
Vrátí tabulku s hodnotami ze všech řádků z aktuální tabulky i tabulky historie.
Poznámky
Klauzule FROM podporuje syntaxi SQL-92 pro spojené tabulky a odvozené tabulky. Syntaxe SQL-92 poskytuje operátory INNER, LEFT OUTER, RIGHT OUTER, FULL OUTER a CROSS join.
Klauzule UNION a JOIN v rámci klauzule FROM jsou podporovány v zobrazeních a v odvozených tabulkách a poddotazech.
Spojení sebe sama je tabulka, která je připojená k sobě. Operace vložení nebo aktualizace založené na vlastním spojení se řídí pořadím v klauzuli FROM.
Vzhledem k tomu, že SQL Server považuje statistiky distribuce a kardinality z propojených serverů, které poskytují statistiky distribuce sloupců, není k vzdálenému vyhodnocení spojení nutné. Procesor dotazů SQL Serveru považuje vzdálené statistiky a určuje, jestli je vhodná strategie vzdáleného připojení. Nápověda ke vzdálenému spojení je užitečná pro poskytovatele, kteří neposkytují statistiky distribuce sloupců.
Použít APPLY
Levý i pravý operand operátoru APPLY jsou výrazy tabulky. Hlavním rozdílem mezi těmito operandy je, že right_table_source může použít funkci s hodnotou tabulky, která přebírá sloupec z left_table_source jako jeden z argumentů funkce. left_table_source může obsahovat funkce s hodnotami tabulky, ale nemůže obsahovat argumenty, které jsou sloupce z right_table_source.
Operátor APPLY funguje následujícím způsobem k vytvoření zdroje tabulky pro klauzuli FROM:
Vyhodnotí right_table_source pro každý řádek left_table_source a vytvoří sady řádků.
Hodnoty v right_table_source závisí na left_table_source. right_table_source lze reprezentovat přibližně tímto způsobem:
TVF(left_table_source.row)
, kdeTVF
je funkce s hodnotou tabulky.Kombinuje sady výsledků vytvořené pro každý řádek při vyhodnocování right_table_source s left_table_source provedením operace UNION ALL.
Seznam sloupců vytvořených výsledkem operátoru APPLY je sada sloupců z left_table_source, která je kombinována se seznamem sloupců z right_table_source.
Použití kontingenční tabulky a funkce UNPIVOT
pivot_column a value_column seskupují sloupce, které používá operátor PIVOT. Pivot se řídí následujícím postupem získání výstupní sady výsledků:
Provede funkci GROUP BY na svém input_table proti sloupcům seskupení a vytvoří jeden výstupní řádek pro každou skupinu.
Seskupování sloupců ve výstupním řádku získá odpovídající hodnoty sloupců pro danou skupinu v input_table.
Vygeneruje hodnoty pro sloupce v seznamu sloupců pro každý výstupní řádek provedením následujících kroků:
Seskupování dalších řádků vygenerovaných v nástroji GROUP BY v předchozím kroku proti pivot_column.
Pro každý výstupní sloupec v column_listvyberte podskupinu, která splňuje podmínku:
pivot_column = CONVERT(<data type of pivot_column>, 'output_column')
aggregate_function se vyhodnotí jako value_column v této podskupině a výsledek se vrátí jako hodnota odpovídajícího output_column. Pokud je podskupina prázdná, SQL Server vygeneruje hodnotu null pro tuto output_column. Pokud je agregační funkce POČET a podskupina je prázdná, vrátí se nula (0).
Poznámka
Identifikátory sloupců v klauzuli UNPIVOT
se řídí kolací katalogu. Pro SQL Database je kolace vždy SQL_Latin1_General_CP1_CI_AS
. U částečně obsažených databází SQL Serveru je kolace vždy Latin1_General_100_CI_AS_KS_WS_SC
. Pokud se sloupec zkombinuje s jinými sloupci, vyžaduje se kompletovací klauzule (COLLATE DATABASE_DEFAULT
), aby nedocházelo ke konfliktům.
Další informace o funkci PIVOT a UNPIVOT včetně příkladů najdete v tématu Použití kontingenční tabulky a funkce UNPIVOT.
Dovolení
Vyžaduje oprávnění pro příkaz DELETE, SELECT nebo UPDATE.
Příklady
A. Použití klauzule FROM
Následující příklad načte sloupce TerritoryID
a Name
z tabulky SalesTerritory
v ukázkové databázi AdventureWorks2022.
SELECT TerritoryID,
Name
FROM Sales.SalesTerritory
ORDER BY TerritoryID;
Tady je sada výsledků.
TerritoryID Name
----------- ------------------------------
1 Northwest
2 Northeast
3 Central
4 Southwest
5 Southeast
6 Canada
7 France
8 Germany
9 Australia
10 United Kingdom
(10 row(s) affected)
B. Použití tipů optimalizátoru TABLOCK a HOLDLOCK
Následující částečná transakce ukazuje, jak umístit explicitní sdílený zámek tabulky na Employee
a jak číst index. Zámek se uchovává v celé transakci.
BEGIN TRANSACTION
SELECT COUNT(*)
FROM HumanResources.Employee WITH (TABLOCK, HOLDLOCK);
C. Použití syntaxe SQL-92 CROSS JOIN
Následující příklad vrátí křížový součin dvou tabulek Employee
a Department
v databázi AdventureWorks2022. Vrátí se seznam všech možných kombinací BusinessEntityID
řádků a všech Department
řádků názvů.
SELECT e.BusinessEntityID,
d.Name AS Department
FROM HumanResources.Employee AS e
CROSS JOIN HumanResources.Department AS d
ORDER BY e.BusinessEntityID,
d.Name;
D. Použití syntaxe SQL-92 FULL OUTER JOIN
Následující příklad vrátí název produktu a všechny odpovídající prodejní objednávky v tabulce SalesOrderDetail
v databázi AdventureWorks2022. Vrátí také všechny prodejní objednávky, které nemají žádný produkt uvedený v tabulce Product
, a všechny produkty s jinou prodejní objednávkou, než je ta uvedená v tabulce Product
.
-- The OUTER keyword following the FULL keyword is optional.
SELECT p.Name,
sod.SalesOrderID
FROM Production.Product AS p
FULL JOIN Sales.SalesOrderDetail AS sod
ON p.ProductID = sod.ProductID
ORDER BY p.Name;
E. Použití syntaxe SQL-92 LEFT OUTER JOIN
Následující příklad spojí dvě tabulky na ProductID
a zachová chybějící řádky z levé tabulky. Tabulka Product
se shoduje s tabulkou SalesOrderDetail
v ProductID
sloupcích v každé tabulce. V sadě výsledků se zobrazí všechny produkty, seřazené a nevyřazené.
SELECT p.Name,
sod.SalesOrderID
FROM Production.Product AS p
LEFT OUTER JOIN Sales.SalesOrderDetail AS sod
ON p.ProductID = sod.ProductID
ORDER BY p.Name;
F. Použití syntaxe SQL-92 INNER JOIN
Následující příklad vrátí všechny názvy produktů a ID prodejních objednávek.
-- By default, SQL Server performs an INNER JOIN if only the JOIN
-- keyword is specified.
SELECT p.Name,
sod.SalesOrderID
FROM Production.Product AS p
INNER JOIN Sales.SalesOrderDetail AS sod
ON p.ProductID = sod.ProductID
ORDER BY p.Name;
G. Použití syntaxe SQL-92 RIGHT OUTER JOIN
Následující příklad spojí dvě tabulky na TerritoryID
a zachová chybějící řádky z pravé tabulky. Tabulka SalesTerritory
se shoduje s tabulkou SalesPerson
ve sloupci TerritoryID
v každé tabulce. V sadě výsledků se zobrazí všichni prodejci bez ohledu na to, jestli mají přiřazenou oblast.
SELECT st.Name AS Territory,
sp.BusinessEntityID
FROM Sales.SalesTerritory AS st
RIGHT OUTER JOIN Sales.SalesPerson AS sp
ON st.TerritoryID = sp.TerritoryID;
H. Použití tipů pro spojení HASH a MERGE
Následující příklad provede spojení se třemi tabulkami mezi Product
, ProductVendor
a Vendor
tabulky pro vytvoření seznamu produktů a jejich dodavatelů. Optimalizátor dotazů spojí Product
a ProductVendor
(p
a pv
) pomocí spojení MERGE. Dále jsou výsledky spojení Product
a ProductVendor
MERGE (p
a pv
) spojené s tabulkou Vendor
pro vytvoření (p
a pv
) a v
.
Důležitý
Po zadání nápovědy ke spojení už není klíčové slovo INNER volitelné a musí být explicitně uvedeno, aby bylo možné provést INNER JOIN.
SELECT p.Name AS ProductName,
v.Name AS VendorName
FROM Production.Product AS p
INNER MERGE JOIN Purchasing.ProductVendor AS pv
ON p.ProductID = pv.ProductID
INNER HASH JOIN Purchasing.Vendor AS v
ON pv.BusinessEntityID = v.BusinessEntityID
ORDER BY p.Name,
v.Name;
Já. Použití odvozené tabulky
Následující příklad používá odvozenou tabulku, SELECT
příkaz za klauzulí FROM
, k vrácení křestního jména a příjmení všech zaměstnanců a měst, ve kterých žijí.
SELECT RTRIM(p.FirstName) + ' ' + LTRIM(p.LastName) AS Name,
d.City
FROM Person.Person AS p
INNER JOIN HumanResources.Employee e
ON p.BusinessEntityID = e.BusinessEntityID
INNER JOIN (
SELECT bea.BusinessEntityID,
a.City
FROM Person.Address AS a
INNER JOIN Person.BusinessEntityAddress AS bea
ON a.AddressID = bea.AddressID
) AS d
ON p.BusinessEntityID = d.BusinessEntityID
ORDER BY p.LastName,
p.FirstName;
J. Použití TABLEAMPLE ke čtení dat ze vzorku řádků v tabulce
Následující příklad používá TABLESAMPLE
v klauzuli FROM
k vrácení přibližně 10
procent všech řádků v tabulce Customer
.
SELECT *
FROM Sales.Customer TABLESAMPLE SYSTEM(10 PERCENT);
K. Použít APPLY
Následující příklad předpokládá, že v databázi existují následující tabulky a funkce s hodnotou tabulky:
Název objektu | Názvy sloupců |
---|---|
Oddělení | DeptID, DivisionID, DeptName, DeptMgrID |
EmpMgr | MgrID, EmpID |
Zaměstnanci | EmpID, EmpLastName, EmpFirstName, EmpSalary |
GetReports(MgrID) | EmpID, EmpLastName, EmpSalary |
Funkce GetReports
hodnotná tabulkou vrátí seznam všech zaměstnanců, kteří hlásí přímo nebo nepřímo zadané MgrID
.
Příklad používá APPLY
k vrácení všech oddělení a všech zaměstnanců v tomto oddělení. Pokud konkrétní oddělení nemá žádné zaměstnance, nebudou pro toto oddělení vráceny žádné řádky.
SELECT DeptID,
DeptName,
DeptMgrID,
EmpID,
EmpLastName,
EmpSalary
FROM Departments d
CROSS APPLY dbo.GetReports(d.DeptMgrID);
Pokud chcete, aby dotaz vytvořil řádky pro tato oddělení bez zaměstnanců, což vytvoří hodnoty null pro EmpID
, EmpLastName
a EmpSalary
sloupce, použijte místo toho OUTER APPLY
.
SELECT DeptID,
DeptName,
DeptMgrID,
EmpID,
EmpLastName,
EmpSalary
FROM Departments d
OUTER APPLY dbo.GetReports(d.DeptMgrID);
L. Použití KŘÍŽOVÉHO POUŽITÍ
Následující příklad načte snímek všech plánů dotazů umístěných v mezipaměti plánu dotazováním zobrazení sys.dm_exec_cached_plans
dynamické správy pro načtení popisovačů plánu všech plánů dotazů v mezipaměti. Potom je zadán operátor CROSS APPLY
pro předání popisovačů plánu sys.dm_exec_query_plan
. Výstup xml Showplan pro každý plán aktuálně v mezipaměti plánu je ve sloupci query_plan
vrácené tabulky.
USE master;
GO
SELECT dbid,
object_id,
query_plan
FROM sys.dm_exec_cached_plans AS cp
CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle);
GO
M. Použití for SYSTEM_TIME
platí pro: SQL Server 2016 (13.x) a novější verze a SQL Database.
Následující příklad používá argument FOR SYSTEM_TIME AS OF date_time_literal_or_variable k vrácení řádků tabulky, které byly skutečné (aktuální) od 1. ledna 2014.
SELECT DepartmentNumber,
DepartmentName,
ManagerID,
ParentDepartmentNumber
FROM DEPARTMENT
FOR SYSTEM_TIME AS OF '2014-01-01'
WHERE ManagerID = 5;
Následující příklad používá argument FOR SYSTEM_TIME FROM date_time_literal_or_variable TO date_time_literal_or_variable k vrácení všech řádků, které byly aktivní během období definovaného od 1. ledna 2013 a končící 1. lednem 2014, s výjimkou horní hranice.
SELECT DepartmentNumber,
DepartmentName,
ManagerID,
ParentDepartmentNumber
FROM DEPARTMENT
FOR SYSTEM_TIME FROM '2013-01-01' TO '2014-01-01'
WHERE ManagerID = 5;
Následující příklad používá argument FOR SYSTEM_TIME BETWEEN date_time_literal_or_variable AND date_time_literal_or_variable k vrácení všech řádků, které byly aktivní během období definovaného od 1. ledna 2013 a končící 1. lednem 2014 včetně horní hranice.
SELECT DepartmentNumber,
DepartmentName,
ManagerID,
ParentDepartmentNumber
FROM DEPARTMENT
FOR SYSTEM_TIME BETWEEN '2013-01-01' AND '2014-01-01'
WHERE ManagerID = 5;
Následující příklad používá argument FOR SYSTEM_TIME OBSAŽENÉ V (date_time_literal_or_variable, date_time_literal_or_variable) k vrácení všech řádků, které byly otevřeny a uzavřeny během období definovaného od 1. ledna 2013 a končí 1. ledna 2014.
SELECT DepartmentNumber,
DepartmentName,
ManagerID,
ParentDepartmentNumber
FROM DEPARTMENT
FOR SYSTEM_TIME CONTAINED IN ('2013-01-01', '2014-01-01')
WHERE ManagerID = 5;
Následující příklad používá proměnnou místo literálu k zadání hodnot hranic kalendářního data pro dotaz.
DECLARE @AsOfFrom DATETIME2 = DATEADD(month, -12, SYSUTCDATETIME());
DECLARE @AsOfTo DATETIME2 = DATEADD(month, -6, SYSUTCDATETIME());
SELECT DepartmentNumber,
DepartmentName,
ManagerID,
ParentDepartmentNumber
FROM DEPARTMENT
FOR SYSTEM_TIME
FROM @AsOfFrom TO @AsOfTo
WHERE ManagerID = 5;
Příklady: Azure Synapse Analytics a Analytický platformový systém (PDW)
N. Použití syntaxe INNER JOIN
Následující příklad vrátí sloupce SalesOrderNumber
, ProductKey
a EnglishProductName
ze FactInternetSales
a DimProduct
tabulek, kde klíč spojení ProductKey
odpovídá v obou tabulkách.
SalesOrderNumber
a EnglishProductName
sloupce existují pouze v jedné z tabulek, takže není nutné specifikovat alias tabulky s těmito sloupci, jak je znázorněno; tyto aliasy jsou zahrnuty pro čitelnost. Slovo AS před názvem aliasu není povinné, ale doporučuje se pro čitelnost a dodržování standardu ANSI.
-- Uses AdventureWorks
SELECT fis.SalesOrderNumber,
dp.ProductKey,
dp.EnglishProductName
FROM FactInternetSales AS fis
INNER JOIN DimProduct AS dp
ON dp.ProductKey = fis.ProductKey;
Vzhledem k tomu, že pro vnitřní spojení není nutné klíčové slovo INNER
, může být tento stejný dotaz napsán jako:
-- Uses AdventureWorks
SELECT fis.SalesOrderNumber,
dp.ProductKey,
dp.EnglishProductName
FROM FactInternetSales AS fis
INNER JOIN DimProduct AS dp
ON dp.ProductKey = fis.ProductKey;
K omezení výsledků je možné použít také klauzuli WHERE
s tímto dotazem. Tento příklad omezuje výsledky na SalesOrderNumber
hodnoty vyšší než SO5000:
-- Uses AdventureWorks
SELECT fis.SalesOrderNumber,
dp.ProductKey,
dp.EnglishProductName
FROM FactInternetSales AS fis
INNER JOIN DimProduct AS dp
ON dp.ProductKey = fis.ProductKey
WHERE fis.SalesOrderNumber > 'SO50000'
ORDER BY fis.SalesOrderNumber;
O. Použití syntaxe LEFT OUTER JOIN a RIGHT OUTER JOIN
Následující příklad spojí tabulky FactInternetSales
a DimProduct
ve sloupcích ProductKey
. Syntaxe levého vnějšího spojení zachovává chybějící řádky z levé tabulky (FactInternetSales
). Vzhledem k tomu, že tabulka FactInternetSales
neobsahuje žádné ProductKey
hodnoty, které neodpovídají DimProduct
tabulce, vrátí tento dotaz stejné řádky jako první příklad vnitřního spojení dříve v tomto článku.
-- Uses AdventureWorks
SELECT fis.SalesOrderNumber,
dp.ProductKey,
dp.EnglishProductName
FROM FactInternetSales AS fis
LEFT OUTER JOIN DimProduct AS dp
ON dp.ProductKey = fis.ProductKey;
Tento dotaz lze také zapsat bez klíčového slova OUTER
.
V pravých vnějších spojeních se zachovají chybějící řádky z pravé tabulky. Následující příklad vrátí stejné řádky jako levý příklad vnějšího spojení výše.
-- Uses AdventureWorks
SELECT fis.SalesOrderNumber,
dp.ProductKey,
dp.EnglishProductName
FROM DimProduct AS dp
RIGHT OUTER JOIN FactInternetSales AS fis
ON dp.ProductKey = fis.ProductKey;
Následující dotaz používá DimSalesTerritory
tabulku jako levou tabulku v levém vnějším spojení. Načte hodnoty SalesOrderNumber
z tabulky FactInternetSales
. Pokud pro konkrétní SalesTerritoryKey
neexistují žádné objednávky, vrátí dotaz hodnotu NULL pro SalesOrderNumber
pro daný řádek. Tento dotaz je seřazený podle sloupce SalesOrderNumber
, aby se všechny hodnoty NUL v tomto sloupci zobrazovaly v horní části výsledků.
-- Uses AdventureWorks
SELECT dst.SalesTerritoryKey,
dst.SalesTerritoryRegion,
fis.SalesOrderNumber
FROM DimSalesTerritory AS dst
LEFT OUTER JOIN FactInternetSales AS fis
ON dst.SalesTerritoryKey = fis.SalesTerritoryKey
ORDER BY fis.SalesOrderNumber;
Tento dotaz se dá přepsat pravým vnějším spojením, aby se načetly stejné výsledky:
-- Uses AdventureWorks
SELECT dst.SalesTerritoryKey,
dst.SalesTerritoryRegion,
fis.SalesOrderNumber
FROM FactInternetSales AS fis
RIGHT OUTER JOIN DimSalesTerritory AS dst
ON fis.SalesTerritoryKey = dst.SalesTerritoryKey
ORDER BY fis.SalesOrderNumber;
P. Použití syntaxe FULL OUTER JOIN
Následující příklad ukazuje úplné vnější spojení, které vrátí všechny řádky z obou spojených tabulek, ale vrátí hodnotu NULL pro hodnoty, které se neshodují z druhé tabulky.
-- Uses AdventureWorks
SELECT dst.SalesTerritoryKey,
dst.SalesTerritoryRegion,
fis.SalesOrderNumber
FROM DimSalesTerritory AS dst
FULL JOIN FactInternetSales AS fis
ON dst.SalesTerritoryKey = fis.SalesTerritoryKey
ORDER BY fis.SalesOrderNumber;
Tento dotaz lze také zapsat bez klíčového slova OUTER
.
-- Uses AdventureWorks
SELECT dst.SalesTerritoryKey,
dst.SalesTerritoryRegion,
fis.SalesOrderNumber
FROM DimSalesTerritory AS dst
FULL JOIN FactInternetSales AS fis
ON dst.SalesTerritoryKey = fis.SalesTerritoryKey
ORDER BY fis.SalesOrderNumber;
Q. Použití syntaxe CROSS JOIN
Následující příklad vrátí křížový součin FactInternetSales
a DimSalesTerritory
tabulek. Vrátí se seznam všech možných kombinací SalesOrderNumber
a SalesTerritoryKey
. Všimněte si absence klauzule ON
v dotazu křížového spojení.
-- Uses AdventureWorks
SELECT dst.SalesTerritoryKey,
fis.SalesOrderNumber
FROM DimSalesTerritory AS dst
CROSS JOIN FactInternetSales AS fis
ORDER BY fis.SalesOrderNumber;
R. Použití odvozené tabulky
Následující příklad používá odvozenou tabulku (příkaz SELECT
za klauzulí FROM
) k vrácení CustomerKey
a LastName
sloupců všech zákazníků v tabulce DimCustomer
s BirthDate
hodnotami pozdějšími než 1. ledna 1970 a příjmením Smith.
-- Uses AdventureWorks
SELECT CustomerKey,
LastName
FROM (
SELECT *
FROM DimCustomer
WHERE BirthDate > '01/01/1970'
) AS DimCustomerDerivedTable
WHERE LastName = 'Smith'
ORDER BY LastName;
S. Příklad nápovědy ke spojení REDUCE
Následující příklad používá nápovědu REDUCE
spojení ke změně zpracování odvozené tabulky v dotazu. Při použití nápovědy REDUCE
spojení v tomto dotazu se fis.ProductKey
promítnou, replikují a zvýrazní a pak připojí k DimProduct
během náhodného prohazování DimProduct
na ProductKey
. Výsledná odvozená tabulka se distribuuje na fis.ProductKey
.
-- Uses AdventureWorks
SELECT SalesOrderNumber
FROM (
SELECT fis.SalesOrderNumber,
dp.ProductKey,
dp.EnglishProductName
FROM DimProduct AS dp
INNER REDUCE JOIN FactInternetSales AS fis
ON dp.ProductKey = fis.ProductKey
) AS dTable
ORDER BY SalesOrderNumber;
T. Příklad nápovědy k replikaci spojení
Tento další příklad ukazuje stejný dotaz jako v předchozím příkladu s tím rozdílem, že místo nápovědy pro spojení REDUCE
se používá tip REPLICATE
spojení. Použití REPLICATE
nápovědy způsobí, že se hodnoty ve sloupci ProductKey
(spojování) z tabulky FactInternetSales
replikují do všech uzlů. Tabulka DimProduct
je připojená k replikované verzi těchto hodnot.
-- Uses AdventureWorks
SELECT SalesOrderNumber
FROM (
SELECT fis.SalesOrderNumber,
dp.ProductKey,
dp.EnglishProductName
FROM DimProduct AS dp
INNER REPLICATE JOIN FactInternetSales AS fis
ON dp.ProductKey = fis.ProductKey
) AS dTable
ORDER BY SalesOrderNumber;
U. Pomocí nápovědy k redistribuci zaručte přesun pro distribuci nekompatibilní spojení.
Následující dotaz používá nápovědu k dotazu REDISTRIBUTE pro distribuci nekompatibilní spojení. To zaručuje, že optimalizátor dotazů používá v plánu dotazu přesun shuffle. To také zaručuje, že plán dotazu nebude používat přesun všesměrového vysílání, který přesune distribuovanou tabulku do replikované tabulky.
V následujícím příkladu vynutí tip REDISTRIBUTE pohyb v tabulce FactInternetSales, protože ProductKey je distribuční sloupec pro DimProduct a není distribučním sloupcem FactInternetSales.
-- Uses AdventureWorks
SELECT dp.ProductKey,
fis.SalesOrderNumber,
fis.TotalProductCost
FROM DimProduct AS dp
INNER REDISTRIBUTE JOIN FactInternetSales AS fis
ON dp.ProductKey = fis.ProductKey;
V. Použití TABLEAMPLE ke čtení dat ze vzorku řádků v tabulce
Následující příklad používá TABLESAMPLE
v klauzuli FROM
k vrácení přibližně 10
procent všech řádků v tabulce Customer
.
SELECT *
FROM Sales.Customer TABLESAMPLE SYSTEM(10 PERCENT);
Související obsah
-
CONTAINSTABLE (Transact-SQL) -
FREETEXTTABLE (Transact-SQL) -
INSERT (Transact-SQL) -
OPENQUERY (Transact-SQL) -
OPENROWSET (Transact-SQL) - operátory (Transact-SQL)
-
WHERE (Transact-SQL)