Try this:
DECLARE @sqlcmd VARCHAR(MAX);
DECLARE @results TABLE (SchemaName NVARCHAR(128), Table_Name NVARCHAR(128), Column_Name NVARCHAR(128), Column_Position INT, DataType VARCHAR(128), max_length INT, AvgLength INT)
SELECT @sqlcmd = STRING_AGG(sqlcmd, CHAR(10))
FROM (
SELECT sqlcmd =
'SELECT
''' + c.TABLE_SCHEMA +''' as SchemaName,
''' + c.TABLE_NAME + ''' as Table_Name,
''' + c.COLUMN_NAME + ''' as Column_Name,
''' + CAST(c.ORDINAL_POSITION AS VARCHAR(10)) + ''' AS Column_Position,
''' + c.DATA_TYPE + ''' AS DataType,
''' + CAST(c.CHARACTER_MAXIMUM_LENGTH AS VARCHAR(10)) + ''' as max_length
, CAST((SELECT AVG(LEN(' + QUOTENAME(c.COLUMN_NAME) + ')) FROM ' + QUOTENAME(c.TABLE_SCHEMA) + '.' + QUOTENAME(c.TABLE_NAME) + ') AS VARCHAR(10)) AS AvgLength'
FROM INFORMATION_SCHEMA.COLUMNS c
INNER JOIN INFORMATION_SCHEMA.TABLES t
ON t.TABLE_CATALOG = c.TABLE_CATALOG
AND t.TABLE_NAME = c.TABLE_NAME
AND t.TABLE_SCHEMA = c.TABLE_SCHEMA
AND t.TABLE_TYPE = 'BASE TABLE'
WHERE c.DATA_TYPE IN ('varchar', 'nvarchar', 'char', 'nchar' )
AND c.CHARACTER_MAXIMUM_LENGTH > 50
AND c.TABLE_SCHEMA = 'dbo'
) c
INSERT INTO @results
EXEC (@sqlcmd);
SELECT *
FROM @results r
ORDER BY r.SchemaName, r.Table_Name, r.Column_Position