Transformando linhas em colunas sem PIVOT

Olá pessoas,

Na semana passada, nós vimos como transformar linhas em colunas no SQL Server com PIVOT. Mas como nem sempre dá para contar com este recurso, e algumas vezes, ele não supre 100% das nossas necessidades, vou apresentar alguns exemplos de como fazer PIVOT sem utilizar PIVOT.

Para estes exemplos, estarei utilizando da mesma massa de dados da semana anterior:

DECLARE @CONTAS TABLE (
	ANO SMALLINT, 
	BANCO VARCHAR(100), 
	TIPO VARCHAR(100), 
	VALOR MONEY
)

INSERT INTO @CONTAS VALUES
(2009,'BANCO ALVORADA S/A','INVESTIMENTOS',6175979775.42),
(2010,'BANCO ALVORADA S/A','INVESTIMENTOS',6486892688.53),
(2011,'BANCO ALVORADA S/A','INVESTIMENTOS',7905663406.86),
(2012,'BANCO ALVORADA S/A','INVESTIMENTOS',9613906084.01),
(2009,'BANCO ARBI S/A','INVESTIMENTOS',8102644.84),
(2009,'BANCO ARBI S/A','OUTROS',174343.35),
(2010,'BANCO ARBI S/A','INVESTIMENTOS',7935411.15),
(2010,'BANCO ARBI S/A','OUTROS',119885.82),
(2011,'BANCO ARBI S/A','INVESTIMENTOS',8202652.29),
(2011,'BANCO ARBI S/A','OUTROS',114215.13),
(2012,'BANCO ARBI S/A','INVESTIMENTOS',8407843.72),
(2012,'BANCO ARBI S/A','OUTROS',81746.25)

Conforme o primeiro exemplo da semana anterior, transformamos os registros de contas do tipo INVESTIMENTOS e OUTROS em duas colunas, utilizando PIVOT:

SELECT U.ANO, U.BANCO, U.INVESTIMENTOS, U.OUTROS
FROM @CONTAS AS C
PIVOT (
	SUM(C.VALOR) FOR
	C.TIPO IN (INVESTIMENTOS, OUTROS)  
) AS U

Sem PIVOT, é possível fazer o mesmo procedimento com CASE WHEN:

SELECT C.ANO, C.BANCO, 
	INVESTIMENTOS = SUM(CASE WHEN C.TIPO = 'INVESTIMENTOS' THEN C.VALOR END),
	OUTROS = SUM(CASE WHEN C.TIPO = 'OUTROS' THEN C.VALOR END)
FROM @CONTAS AS C
GROUP BY C.ANO, C.BANCO

E no SQL Server 2012+, com IIF:

SELECT C.ANO, C.BANCO, 
	INVESTIMENTOS = SUM(IIF(C.TIPO = 'INVESTIMENTOS', C.VALOR, NULL)),
	OUTROS = SUM(IIF(C.TIPO = 'OUTROS', C.VALOR, NULL))
FROM @CONTAS AS C
GROUP BY C.ANO, C.BANCO

Também é possível fazer com subqueries, mas como não é performático, então ignoraremos esta alternativa.

O segundo exemplo, transformamos os registros de anos em colunas respectivas a estes anos, utilizando PIVOT:

SELECT U.BANCO, U.TIPO, U.[2009], U.[2010], U.[2011], U.[2012]
FROM @CONTAS AS C
PIVOT (
	SUM(C.VALOR) FOR
	C.ANO IN ([2009], [2010], [2011], [2012])  
) AS U

Sem PIVOT, é possível fazer o mesmo procedimento com CASE WHEN:

SELECT C.BANCO, C.TIPO,
	[2009] = SUM(CASE WHEN C.ANO = 2009 THEN C.VALOR END),
	[2010] = SUM(CASE WHEN C.ANO = 2010 THEN C.VALOR END),
	[2011] = SUM(CASE WHEN C.ANO = 2011 THEN C.VALOR END),
	[2012] = SUM(CASE WHEN C.ANO = 2012 THEN C.VALOR END)
FROM @CONTAS AS C
GROUP BY C.BANCO, C.TIPO

E no SQL Server 2012+, com IIF:

SELECT C.BANCO, C.TIPO,
	[2009] = SUM(IIF(C.ANO = 2009, C.VALOR, NULL)),
	[2010] = SUM(IIF(C.ANO = 2010, C.VALOR, NULL)),
	[2011] = SUM(IIF(C.ANO = 2011, C.VALOR, NULL)),
	[2012] = SUM(IIF(C.ANO = 2012, C.VALOR, NULL))
FROM @CONTAS AS C
GROUP BY C.BANCO, C.TIPO

E agora, algumas questões que são mais fáceis de resolver com CASE WHEN e IIF, como criar regras mais específicas para as colunas utilizando outras funções e outras regras de agrupamento:

SELECT U.BANCO, U.TIPO,
	U.[2008], U.[2009], U.[2010], U.[2011], U.[2012], 
	[2009_2010] = U.[2009] + U.[2010],
	[2011_2012] = U.[2011] + U.[2012], 
	TOTAL = U.[2009] + U.[2010] + U.[2011] + U.[2012]
FROM @CONTAS AS C
PIVOT (
	SUM(C.VALOR) FOR
	C.ANO IN ([2008], [2009], [2010], [2011], [2012])  
) AS U

SELECT C.BANCO, C.TIPO,
	[2008] = SUM(CASE WHEN C.ANO = 2008 THEN C.VALOR ELSE 0 END),
	[2009] = SUM(CASE WHEN C.ANO = 2009 THEN C.VALOR ELSE 0 END),
	[2010] = SUM(CASE WHEN C.ANO = 2010 THEN C.VALOR ELSE 0 END),
	[2011] = SUM(CASE WHEN C.ANO = 2011 THEN C.VALOR ELSE 0 END),
	[2012] = SUM(CASE WHEN C.ANO = 2012 THEN C.VALOR ELSE 0 END),
	[!2012] = SUM(CASE WHEN C.ANO <> 2012 THEN C.VALOR ELSE 0 END),
	[<2012] = SUM(CASE WHEN C.ANO < 2012 THEN C.VALOR ELSE 0 END),
	[2009_2010] = SUM(CASE WHEN C.ANO IN (2009, 2010) THEN C.VALOR ELSE 0 END),
	[2011_2012] = SUM(CASE WHEN C.ANO BETWEEN 2011 AND 2012 THEN C.VALOR ELSE 0 END),
	TOTAL = SUM(C.VALOR),
	MEDIA = AVG(C.VALOR)
FROM @CONTAS AS C
GROUP BY C.BANCO, C.TIPO

SELECT C.BANCO, C.TIPO,
	[2008] = SUM(IIF(C.ANO = 2008, C.VALOR, 0)),
	[2009] = SUM(IIF(C.ANO = 2009, C.VALOR, 0)),
	[2010] = SUM(IIF(C.ANO = 2010, C.VALOR, 0)),
	[2011] = SUM(IIF(C.ANO = 2011, C.VALOR, 0)),
	[2012] = SUM(IIF(C.ANO = 2012, C.VALOR, 0)),
	[!2012] = SUM(IIF(C.ANO <> 2012, C.VALOR, 0)),
	[<2012] = SUM(IIF(C.ANO < 2012, C.VALOR, 0)),
	[2009_2010] = SUM(IIF(C.ANO IN (2009, 2010), C.VALOR, 0)),
	[2011_2012] = SUM(IIF(C.ANO BETWEEN 2011 AND 2012, C.VALOR, 0)),
	TOTAL = SUM(C.VALOR),
	MEDIA = AVG(C.VALOR)
FROM @CONTAS AS C
GROUP BY C.BANCO, C.TIPO

E a composição de um agrupamento de linhas para colunas com considerando mais de uma coluna:

SELECT BANCO = COALESCE(U_I.BANCO, U_O.BANCO), 
	INV_2009 = U_I.[2009], 
	INV_2010 = U_I.[2010], 
	INV_2011 = U_I.[2011], 
	INV_2012 = U_I.[2012], 
	OUT_2009 = U_O.[2009], 
	OUT_2010 = U_O.[2010], 
	OUT_2011 = U_O.[2011], 
	OUT_2012 = U_O.[2012]
FROM 
(SELECT BANCO, ANO, VALOR FROM @CONTAS WHERE TIPO = 'INVESTIMENTOS') AS C_I
PIVOT (
	SUM(C_I.VALOR) FOR
	C_I.ANO IN ([2009], [2010], [2011], [2012])  
) AS U_I
FULL OUTER JOIN
(SELECT BANCO, ANO, VALOR FROM @CONTAS WHERE TIPO = 'OUTROS') AS C_O
PIVOT (
	SUM(C_O.VALOR) FOR
	C_O.ANO IN ([2009], [2010], [2011], [2012])  
) AS U_O
ON U_I.BANCO = U_O.BANCO
SELECT C.BANCO,
	INV_2009 = SUM(CASE WHEN C.ANO = 2009 AND TIPO = 'INVESTIMENTOS' THEN C.VALOR ELSE 0 END),
	INV_2010 = SUM(CASE WHEN C.ANO = 2010 AND TIPO = 'INVESTIMENTOS' THEN C.VALOR ELSE 0 END),
	INV_2011 = SUM(CASE WHEN C.ANO = 2011 AND TIPO = 'INVESTIMENTOS' THEN C.VALOR ELSE 0 END),
	INV_2012 = SUM(CASE WHEN C.ANO = 2012 AND TIPO = 'INVESTIMENTOS' THEN C.VALOR ELSE 0 END), 
	OUT_2009 = SUM(CASE WHEN C.ANO = 2009 AND TIPO = 'OUTROS' THEN C.VALOR ELSE 0 END), 
	OUT_2010 = SUM(CASE WHEN C.ANO = 2010 AND TIPO = 'OUTROS' THEN C.VALOR ELSE 0 END), 
	OUT_2011 = SUM(CASE WHEN C.ANO = 2011 AND TIPO = 'OUTROS' THEN C.VALOR ELSE 0 END), 
	OUT_2012 = SUM(CASE WHEN C.ANO = 2012 AND TIPO = 'OUTROS' THEN C.VALOR ELSE 0 END)
FROM @CONTAS AS C
GROUP BY C.BANCO
SELECT C.BANCO,
	INV_2009 = SUM(IIF(C.ANO = 2009 AND TIPO = 'INVESTIMENTOS', C.VALOR, 0)),
	INV_2010 = SUM(IIF(C.ANO = 2010 AND TIPO = 'INVESTIMENTOS', C.VALOR, 0)),
	INV_2011 = SUM(IIF(C.ANO = 2011 AND TIPO = 'INVESTIMENTOS', C.VALOR, 0)),
	INV_2012 = SUM(IIF(C.ANO = 2012 AND TIPO = 'INVESTIMENTOS', C.VALOR, 0)), 
	OUT_2009 = SUM(IIF(C.ANO = 2009 AND TIPO = 'OUTROS', C.VALOR, 0)), 
	OUT_2010 = SUM(IIF(C.ANO = 2010 AND TIPO = 'OUTROS', C.VALOR, 0)), 
	OUT_2011 = SUM(IIF(C.ANO = 2011 AND TIPO = 'OUTROS', C.VALOR, 0)), 
	OUT_2012 = SUM(IIF(C.ANO = 2012 AND TIPO = 'OUTROS', C.VALOR, 0))
FROM @CONTAS AS C
GROUP BY C.BANCO
Anúncios

SQL Server 2012 “Denali” CTP 3 – Resumo

Para terminar a segunda série de artigos sobre o SQL Server Denali iniciada na semana passada, segue uma relação de artigos publicados sobre SQL Server 2012 Denali CTP 3 nestes últimos dias e um upgrade do resumo dos artigos que foram publicados desde o CTP 1.

Links gerais:

SQL Server Denali Wallpaper:
http://sqlblog.com/blogs/argenis_fernandez/archive/2011/06/09/sql-server-denali-wallpaper.aspx

Adventure Works for SQL Server Denali CTP3:
http://msftdbprodsamples.codeplex.com/releases/view/55330

e-book grátis do SQL Server 2012:
http://magalhaesv.wordpress.com/2011/10/13/e-book-gratis-do-sql-2012

Artigos em português:

Felipe Ferreira: SQL Server Denali CTP3:
http://blogs.solidq.com/fferreira/Post.aspx?ID=36

Antes DBCC SQLPERF(LOGSPACE), agora dm_db_log_space_usage
http://marcosfreccia.wordpress.com/2011/07/17/sql-server-denali-dm_db_log_space_usage

Novas funções: FORMAT e CONCAT
https://sqlfromhell.wordpress.com/2011/07/20/sql-server-denali-ctp3-novas-funcoes-format-e-concat

Novas funções: IIF e CHOOSE
https://sqlfromhell.wordpress.com/2011/07/19/sql-server-denali-ctp3-%e2%80%93-novas-funcoes-iif-e-choose

Novas funções de data: EOMONTH e DATETIMEFROMPARTS
https://sqlfromhell.wordpress.com/2011/07/18/sql-server-denali-ctp3-novas-funcoes-de-data

Novas funções: PARSE e TRY_CONVERT
https://sqlfromhell.wordpress.com/2011/07/15/sql-server-denali-ctp3-novas-funcoes-parse-e-try_convert

Funções Analíticas: FIRST_VALUE e LAST_VALUE
https://sqlfromhell.wordpress.com/2011/07/20/sql-server-denali-ctp3-funcoes-analiticas-first_value-e-last_value

Fabiano Neves Amorim: Funções Analíticas:
http://blogs.solidq.com/fabianosqlserver/Post.aspx?ID=58
http://blogs.solidq.com/fabianosqlserver/Post.aspx?ID=64

Problema: Serviço não inicia após a instalação
https://sqlfromhell.wordpress.com/2011/07/14/problemas-com-a-instalacao-do-denali-ctp-3-servico-nao-inicia

Artigos em francês:

Installation de SQL Server Denali CTP3 :
http://conseilit.wordpress.com/2011/07/12/installation-de-sql-server-denali-ctp3

Clause OVER étendue:
http://conseilit.wordpress.com/2011/07/15/denali-ctp3-clause-over-tendue

Comptes de service:
http://conseilit.wordpress.com/2011/07/12/denali-comptes-de-service

Artigos em inglês:

CTP3 is Here! Five Things to Know About the Next Version of SQL Server:
http://www.brentozar.com/archive/2011/07/five-things-sql-server-denali-ctp3

Policy-Based Management:
http://sqlserverpedia.com/blog/sql-server-bloggers/sql-server-denali-ctp3-policy-based-management

Tabular Model, Columnstore, new BIDS released!
http://apandre.wordpress.com/2011/07/14/tabular-model

SQL Server Project “Crescent” – Overview:
http://social.technet.microsoft.com/wiki/contents/articles/project-crescent-overview.aspx

SQL Server Project “Crescent” – Demo from WPC11:
http://blogs.technet.com/b/dataplatforminsider/archive/2011/07/18/new-sql-server-project-quot-crescent-quot-demo.aspx

SQL Server Columnstore Index FAQ:
http://social.technet.microsoft.com/wiki/contents/articles/sql-server-columnstore-index-faq.aspx

Restore improvements in SQL Server Denali CTP3 Management Studio:
http://blogs.msdn.com/b/wesleyb/archive/2011/07/18/restore-improvements-in-sql-server-denali-ctp3-management-studio.aspx

Artigos do SQL Server Denali CTP 1 em português:

Column Store – Felipe Ferreira:
http://blogs.solidq.com/fferreira/Post.aspx?ID=12&title=SQL+Denali+%e2%80%93+ColumnStore

Sequences:
https://sqlfromhell.wordpress.com/2010/11/10/sql-server-2011-ctp-1-sequences

Novidades do ORDER BY:
https://sqlfromhell.wordpress.com/2010/11/10/sql-server-2011-ctp-1-novidades-do-order-by

Contained Database e Usuários:
https://sqlfromhell.wordpress.com/2010/11/16/sql-server-2011-contained-database

Criando Server Roles:
https://sqlfromhell.wordpress.com/2010/11/17/sql-server-2011-server-roles

RESULT SETS:
https://sqlfromhell.wordpress.com/2010/11/22/sql-server-2011-result-sets-1
https://sqlfromhell.wordpress.com/2010/11/23/sql-server-2011-result-sets-2

SQL Server Denali CTP 1 – Resumo:
https://sqlfromhell.wordpress.com/2010/11/29/sql-server-2011-ctp-1-resumo

Fabrício Lima: SQL Server Denali CTP 1:
http://fabriciodba.wordpress.com/2010/11/14/sql-server-11-codinome-denali

Artigos do SQL Server Denali CTP 1 em inglês:

Full Text Search with Extended Properties – Bob Beauchemin:
http://www.sqlskills.com/BLOGS/BOBB/post/Using-SQL-Server-Denali-Full-Text-Search-With-Extended-Properties.aspx

Exploring THROW – Aaron Bertrand:
http://sqlblog.com/blogs/aaron_bertrand/archive/2010/11/22/sql-server-v-next-denali-using-throw-instead-of-raiserror.aspx

New SSMS – Aaron Bertrand:
http://sqlblog.com/blogs/aaron_bertrand/archive/2010/11/23/sql-server-11-denali-the-new-vs-shell.aspx

Change Startup Parameter – DBATAG:
http://sqlserver-training.com/sql-server-denali-changed-startup-parameter-new-feature

SQL Server 2012 “Denali” CTP3 – Funções Analíticas: FIRST_VALUE e LAST_VALUE

Surgiram ainda outras novas funções no SQL Server Denali CTP3, como a FIRST_VALUE() que simplifica cenários que necessitam recuperar o primeiro ou último valor de uma da coluna.

Após ler este artigo, dê uma olhada nas recomendações, onde relacionei artigos sobre funções analíticas de duas feras em SQL Server, Christophe LAPORTE (MCM) e Fabiano Neves Amorim (SolidQ).

Para os exemplos da função FIRST_VALUE(), vamos criar um cenário simples, com uma tabela com alguns registros com nomes e horários:

Antes da função FIRST_VALUE, era necessário alguma forma de sub consulta para ter em uma coluna o valor do primeiro registro:

Agora com o Denali, temos a função FIRST_VALUE para simplificar um pouco este cenário:

Assim como recuperar o último valor (penso que esta situação poderá ser substituída pela função LAST_VALUE nos próximos releases):

No caso de recuperar a primeira hora (HORA) de cada pessoa (NOME), antes do Denali tínhamos que usar uma clausula WHERE sobre a sub consulta:

Situação que pode ser facilmente simplificada com PARTITION BY:

Seria um problema da função LAST_VALUE()?

Em relação à função LAST_VALUE, ainda não descobri como ela funciona no SQL Server Denali, pois ao meu entendimento ela deveria trazer o último valor, no entanto, nos testes que realizei com ela não retornou nada além do valor corrente. Pelo que vi no artigo do Christophe LAPORTE, não sou o único que não se entendeu com esta função.

Recomendações:

Quem gostou das funções analíticas e quer conhecer um pouco mais sobre estas e outras funções que estão presentes no SQL Server Denali CTP 3, recomendo dar uma olhada nos seguintes artigos

Christophe LAPORTE: Denali CTP3 – Clause OVER étendue (artigo em francês)
http://conseilit.wordpress.com/2011/07/15/denali-ctp3-clause-over-tendue

Fabiano Neves Amorim: SQL Server – Windows Functions (artigos em português)
http://blogs.solidq.com/fabianosqlserver/Post.aspx?ID=58
http://blogs.solidq.com/fabianosqlserver/Post.aspx?ID=64

Referências:

Books Online for SQL Server “Denali”: Analytic Functions
http://msdn.microsoft.com/en-us/library/hh213234(v=SQL.110).aspx

SQL Server 2012 “Denali” CTP3 – Novas funções: FORMAT e CONCAT

Continuando a relação das novas funções que estão disponíveis no SQL Server Denali, temos a função FORMAT, que permite maior flexibilidade na formatação de dados e a função CONCAT que facilita questões de concatenação de dados para o formato de texto.

Função FORMAT

A função FORMAT, como as novas funções PARSE e TRY_PARSE tratadas no artigo anterior, é mais uma das que herdaram as questões de cultura da .NET Framework (ex.: pt-BR, en-US, fr-FR) e também pode ser uma alternativa para substituir a função CONVERT e CAST quem questões que exijam mais flexibilidade para formatação.

Para o primeiro exemplo, temos a flexibilidade de formatar valores numéricos e decimais, contando também com aspectos de cultura (opcional):

Outro recurso que poderá auxiliar muito quem trabalha com projetos internacionais, são as formatações monetárias:

E as formatações de data/hora baseada em alguma cultura ou a partir de um formato explícito:

Mais informações para entender como utilizar as expressões de formatação:
http://msdn.microsoft.com/en-us/library/26etazsy.aspx

Função CONCAT

Não vou ser hipócrita de dizer que a nova função CONCAT é uma daquelas funções que você não viveria sem, mas ainda sim é uma função que pode ser útil, além de evitar os tradicionais problemas com conversão de dados:

E ainda funciona bem sem ter problemas com a configuração CONCAT_NULL_YIELDS_NULL, que já tinha me dado alguns traumas com concatenação simples de texto (+), exemplo:

SQL Server 2012 “Denali” CTP3 – Novas funções: IIF e CHOOSE

Quando vi no “Books Online” as funções IIF e CHOOSE para o SQL Server Denali CTP3, pensei de imediato que finalmente será possível substituir alguns “CASE WHEN THEN END” para algo mais limpo!

Mas antes de pensar em IIF() e CHOOSE(), um lembrete extremamente importante: ISNULL(), NULLIF() e CASE WHEN não morreram no SQL Server Denali, Amen!

Função IIF

Para mostrar como o código ficou mais limpo com IIF, abaixo exemplos da utilização do CASE e a mesma lógica com IIF:

Mas isso não quer dizer que as expressões ficaram restritas com IIF, exemplo:

(Os exemplos com EXISTS e COLLATE ficaram bizarros…)

Função CHOOSE

Também temos exemplos de código mais limpo com o uso de CHOOSE ao invés do tradicional CASE:

Note que assim como na utilização do CASE, o CHOOSE retorna NULL quando não existe uma alternativa válida como resultado:

Mas como não contamos com um ELSE na função CHOOSE, temos que utilizar um ISNULL para retornar um valor padrão nas situações que não possuem alternativa válida:

Recomendação

Por fim, não comece a substituir CASE e as funções ISNULL, NULLIF por CHOOSE e IIF só porque “fica mais bonito”.

SQL Server 2012 “Denali” CTP3 – Novas funções de data

No SQL Server Denali CTP3 também foram lançadas algumas funções relacionadas à data e hora, sendo estas também bem úteis para o dia-a-dia dos DBAs e desenvolvedores.

Gerando dados do tipo DATE, TIME, SMALLDATETIME e DATETIME

O primeiro grupo de funções que apresentarei neste artigo são as funções DATEFORMPARTS, TIMEFROMPARTS, SMALLDATETIMEFROMPARTS e DATETIMEFROMPARTS, que permitem gerar dados do tipo DATE, TIME, SMALLDATETIME e DATETIME respectivamente com muita facilidade, exemplo:

Gerando DATETIME2 e DATETIMEOFFSET

No caso do uso de tipos de dados de data com muita precisão de milissegundos, teremos problemas com o DATETIME visto que ele não possui uma precisão tão boa, assim podemos utilizar DATETIME2 ou DATETIMEOFFSET, cujas precisões são configuráveis e precisas, por meio das funções DATETIME2FROMPARTS e DATETIMEOFFSETFROMPARTS respectivamente, exemplo:

Função EOMONTH

Também esta disponível a função EOMONTH ou “END OF MONTH” (fim do mês), que permite identificar o último dia do mês de uma data informada, exemplo:

Amanhã teremos mais um artigo sobre o SQL Server Denali CTP3!

SQL Server 2012 “Denali” CTP3 – Novas funções: PARSE e TRY_CONVERT

Dentre as funções que foram lançadas com este novo CTP do SQL Server Denali, temos algumas que realmente facilitam e muito o dia-a-dia dos DBAs e desenvolvedores, sendo as principais: PARSE, TRY_PARSE e TRY_CONVERT.

Função TRY_CONVERT

A partir de agora, ao invés de receber mensagens de erro como “The conversion of a varchar data type to a datetime data type resulted in an out-of-range value” ou ter que desenvolver suas próprias funções de CONVERT para situações que podem gerar erros, temos o TRY_CONVERT. O TRY_CONVERT permite converter valores da mesma forma que a função CONVERT, com o diferencial de não gerar erro quando não é possível recuperar um valor, exemplo:

Função PARSE

Também foram inseridas neste CTP as funções de PARSE, que permitem conversão de textos para algum tipo escolhido, também com a possibilidade de informar qual a cultura a ser utilizada, exemplo “pt-BR” (Brasil) e “en-US” (Inglês USA), utilizando nativamente CLR:

Função TRY_PARSE

Também o método PARSE possui sua variação TRY_PARSE, que retorna NULL quando não for possível a conversão:

Próxima semana, também apresentarei novas funcionalidades que estão disponíveis neste CTP!