TSQL Challenge 21 - Solution By Jesse Roberge



--TSQLContest21Submission_JesseRoberge.sql
WITH
	N4           AS (SELECT 1 AS C UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1)
	,N16         AS (SELECT 1 AS C FROM N4 AS A CROSS JOIN N4 AS B)
	,N256        AS (SELECT 1 AS C FROM N16 AS A CROSS JOIN N16 AS B)
	,N65536      AS (SELECT 1 AS C FROM N256 AS A CROSS JOIN N256 AS B)
	,Numbers     AS (SELECT ROW_NUMBER() OVER(ORDER BY (SELECT 1)) AS PK_CountID FROM N65536)
	,ScanNumberMap AS (
		SELECT NULL AS RowPos, NULL AS Digit, NULL AS ScanNumber WHERE 1=2 UNION ALL
		SELECT 1, 'S', CONVERT(Char(3), '###') UNION ALL
		SELECT 2, 'S', CONVERT(Char(3), '###') UNION ALL
		SELECT 3, 'S', CONVERT(Char(3), '###') UNION ALL
		SELECT 1, '0', CONVERT(Char(3), '#_#') UNION ALL
		SELECT 2, '0', CONVERT(Char(3), '|#|') UNION ALL
		SELECT 3, '0', CONVERT(Char(3), '|_|') UNION ALL
		SELECT 1, '1', CONVERT(Char(3), '###') UNION ALL
		SELECT 2, '1', CONVERT(Char(3), '##|') UNION ALL
		SELECT 3, '1', CONVERT(Char(3), '##|') UNION ALL
		SELECT 1, '2', CONVERT(Char(3), '#_#') UNION ALL
		SELECT 2, '2', CONVERT(Char(3), '#_|') UNION ALL
		SELECT 3, '2', CONVERT(Char(3), '|_#') UNION ALL
		SELECT 1, '3', CONVERT(Char(3), '#_#') UNION ALL
		SELECT 2, '3', CONVERT(Char(3), '#_|') UNION ALL
		SELECT 3, '3', CONVERT(Char(3), '#_|') UNION ALL
		SELECT 1, '4', CONVERT(Char(3), '###') UNION ALL
		SELECT 2, '4', CONVERT(Char(3), '|_|') UNION ALL
		SELECT 3, '4', CONVERT(Char(3), '##|') UNION ALL
		SELECT 1, '5', CONVERT(Char(3), '#_#') UNION ALL
		SELECT 2, '5', CONVERT(Char(3), '|_#') UNION ALL
		SELECT 3, '5', CONVERT(Char(3), '#_|') UNION ALL
		SELECT 1, '6', CONVERT(Char(3), '#_#') UNION ALL
		SELECT 2, '6', CONVERT(Char(3), '|_#') UNION ALL
		SELECT 3, '6', CONVERT(Char(3), '|_|') UNION ALL
		SELECT 1, '7', CONVERT(Char(3), '#_#') UNION ALL
		SELECT 2, '7', CONVERT(Char(3), '##|') UNION ALL
		SELECT 3, '7', CONVERT(Char(3), '##|') UNION ALL
		SELECT 1, '8', CONVERT(Char(3), '#_#') UNION ALL
		SELECT 2, '8', CONVERT(Char(3), '|_|') UNION ALL
		SELECT 3, '8', CONVERT(Char(3), '|_|') UNION ALL
		SELECT 1, '9', CONVERT(Char(3), '#_#') UNION ALL
		SELECT 2, '9', CONVERT(Char(3), '|_|') UNION ALL
		SELECT 3, '9', CONVERT(Char(3), '#_|')
	)
	,DSource  AS (
		SELECT ID, REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(CONVERT(VarChar(1000), ScanNumber), Char(13), ','), Char(10), '*'), ',*', ','), '*,', ','), '*', ','), ' ', '#') AS ScanNumber
		FROM @T AS DataSource
	),
	DataSource AS (
		SELECT ID, (LEN(SubString(ScanNumber, 1, CharIndex(',', ScanNumber)-1))+2)/3 AS DigitCount, ScanNumber
		FROM DSource
	)
	,SourceScanNumbers AS (
		SELECT
			DataSource.ID,
			--Cross Apply with one ID at a time to be able to use FOR XML PATH('') Concatenation
			(
				SELECT ISNULL(Number.Digit,'X')
				FROM
					--Generate placeholders (this has unfortunately caused a table spool to occur in the query plan)
					(
						SELECT Numbers.PK_CountID AS ColPos
						FROM Numbers
						WHERE Numbers.PK_CountID BETWEEN 1 AND DataSource.DigitCount
					) AS Placeholder
					--Parse the dgits
					LEFT OUTER JOIN (
						SELECT Number.ColPos, Number.Digit
						FROM
							(
								--Preprocess the digit so it is not repeat-processed in the GROUP BY
								SELECT SourceNumbers.ColPos, ISNULL(ScanNumberMap.Digit, 'X') AS Digit
								FROM
									--Separate the rows
									(
										SELECT
											ROW_NUMBER() OVER (ORDER BY PK_CountID) AS RowPos,
											SUBSTRING(DataSource.ScanNumber+',', PK_CountID, CHARINDEX(',', DataSource.ScanNumber+',', PK_CountID)-PK_CountID) AS ScanNumber
										FROM Numbers
										WHERE PK_CountID >0 AND PK_CountID<LEN(DataSource.ScanNumber)+LEN(',') AND SubString(',' + DataSource.ScanNumber + ',', PK_CountID, 1)=','
									) AS SourceScanNumbers
									--Separate the digits to a row-digit matrix
									OUTER APPLY (
										SELECT PK_CountID AS ColPos, SubString(SourceScanNumbers.ScanNumber, PK_CountID*3-2, 3) AS ScanNumberSingle
										FROM Numbers
										WHERE PK_CountID BETWEEN 1 AND DataSource.DigitCount
									) AS SourceNumbers
									--Cross-reference with mapping pseudo-temp-table (hardcoded constants formed by UNION ALL row constructors)
									LEFT OUTER JOIN ScanNumberMap ON SourceScanNumbers.RowPos=ScanNumberMap.RowPos AND SourceNumbers.ScanNumberSingle=ScanNumberMap.ScanNumber
								--First three rows only.
								WHERE
									SourceScanNumbers.RowPos<4 AND SourceNumbers.ColPos<=DataSource.DigitCount
							) AS Number
						GROUP BY Number.ColPos, Number.Digit
						HAVING COUNT(*)>2
					) AS Number ON PlaceHolder.ColPos=Number.ColPos
				ORDER BY PlaceHolder.ColPos, Digit
				FOR XML PATH ('')
			) AS Number

		FROM DataSource
	)
SELECT ID, REPLACE(Number, 'S', ' ') AS Number
FROM SourceScanNumbers
ORDER BY ID


Did you find something incorrect/wrong with this solution? Take a few seconds to Report It.

Did you understand how this solution work? If you find it difficult to understand, you can Request an Explanation or you can Write an explanation to help others better understand this solution.