L'altro ragazzo aveva torto come sospettavo, quindi risponderò alla mia stessa domanda.
In SQL Server 2012 (e probabilmente nelle versioni precedenti), ho scoperto che se chiamo 'set showplan_xml on;' su una query arbitraria come:
select * from (select * from Lessons a) a inner join (select * from LessonTypes b) b on a.LessonTypeID = b.ID;
L'XML restituito include quanto segue come OutputList di primo livello/primo livello, che mostra chiaramente tutte le colonne e non solo le tabelle di origine, ma anche l'alias della sottoquery di origine.
<OutputList>
<ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[a]" Column="ID"/>
<ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[a]" Column="Name"/>
<ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[a]" Column="Description"/>
<ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[a]" Column="Enabled"/>
<ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[a]" Column="LessonTypeID"/>
<ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[LessonTypes]" Alias="[b]" Column="ID"/>
<ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[LessonTypes]" Alias="[b]" Column="Name"/>
<ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[LessonTypes]" Alias="[b]" Column="Description"/>
</OutputList>
Quindi, nell'API del mio database, dal momento che memorizzo tutte le stringhe di query in modo ordinato in un dizionario, posso effettivamente eseguire un riscaldamento della cache all'avvio dell'applicazione che le esegue tutte con xml_showplan su, analizzo le colonne di output di primo livello XML e quindi avere una mappatura completa degli alias delle tabelle e dei nomi delle colonne al loro ordinale di output.
In realtà, ho usato un piccolo trucco qui. In realtà non è l'alias della sottoquery, ma l'alias della tabella di base. Se non si include un alias nella tabella di base, l'attributo Alias non è presente nell'XML. Tuttavia, è molto semplice assicurarsi che ogni volta che si fa riferimento a una tabella reale, le si assegna un alias, che dovrebbe far sì che venga restituito all'XML e il gioco è fatto.
Giusto per portare a casa il punto, gli alias rimangono, anche quando si unisce la tabella a se stessa in una query come:
select * from Lessons a, Lessons b, Lessons c
, che produce:
<OutputList>
<ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[a]" Column="ID"/>
<ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[a]" Column="Name"/>
<ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[a]" Column="Description"/>
<ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[a]" Column="Enabled"/>
<ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[a]" Column="LessonTypeID"/>
<ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[b]" Column="ID"/>
<ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[b]" Column="Name"/>
<ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[b]" Column="Description"/>
<ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[b]" Column="Enabled"/>
<ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[b]" Column="LessonTypeID"/>
<ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[c]" Column="ID"/>
<ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[c]" Column="Name"/>
<ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[c]" Column="Description"/>
<ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[c]" Column="Enabled"/>
<ColumnReference Database="[sensitive]" Schema="[dbo]" Table="[Lessons]" Alias="[c]" Column="LessonTypeID"/>
</OutputList>
Quindi, come puoi vedere, gli alias sono infatti intatti e recuperabili.