This challenge has been seen in one of the SQL Server forums. The challenge is all about merging the data based on certain conditions.
- Sample Data
ID Name -- ------------------ 1 Deepak Kumar Goyal 2 Niladri Biswas 2 Pratik Shaw 3 Sumi Girijan 3 Suresh Beldar 3 Jeeva BabyThe challenge is that if the Id’s are exactly two in number (e.g. count of ID = 2 is exactly two ) then the names should be concatenated with 'OR'. When Ids are more than two (e.g. Id # 3 has a count of 3) , the values should be concatenated with 'AND'
- Expected Results
ID Name -- --------------------------------------------- 1 Deepak Kumar Goyal 2 Niladri Biswas OR Pratik Shaw 3 Sumi Girijan AND Suresh Beldar AND Jeeva Baby
- Rules
- The program should run in SQL SERVER 2005+.
- Column names should respect the desired output shown.
- There should be exactly 1 space before and after the OR/AND clause.
- Output should be in the order of Ascending Id.
- Names should not be repeated even if it is given in the sample input i.e. if X is appearing more than once in the input for id = 10, the desired output will have only one such record.
- Names cannot be blank e.g. for id = 10 if the Name field is ‘’(blank), the program should ignore that.
- 個人解法
DECLARE @t TABLE( ID INT, NAME VARCHAR(MAX) ) INSERT INTO @t (ID,[NAME]) SELECT 1, 'Deepak Kumar Goyal' INSERT INTO @t (ID,[NAME]) SELECT 2, 'Niladri Biswas' INSERT INTO @t (ID,[NAME]) SELECT 2, 'Pratik Shaw' INSERT INTO @t (ID,[NAME]) SELECT 3, 'Sumi Girijan' INSERT INTO @t (ID,[NAME]) SELECT 3, 'Suresh Beldar' INSERT INTO @t (ID,[NAME]) SELECT 3, 'Jeeva Baby' ; WITH CTE AS ( SELECT ID , [Name] , COUNT(ID) OVER (PARTITION BY ID) AS counts FROM @t WHERE LEN([Name]) > 0 ) SELECT F.ID , CASE WHEN CHARINDEX('OR',F.[Name]) > 0 THEN SUBSTRING(F.[Name],5,LEN(F.[Name])-4) WHEN CHARINDEX('AND',F.[Name]) > 0 THEN SUBSTRING(F.[Name],6,LEN(F.[Name])-5) ELSE F.[Name] END AS [Name] FROM ( SELECT T1.ID , ( SELECT CASE WHEN counts = 2 THEN ' OR ' WHEN counts > 2 THEN ' AND ' ELSE '' END + T2.[Name] FROM CTE AS T2 WHERE T1.ID = T2.ID FOR XML PATH('') ) AS [Name] FROM CTE AS T1 GROUP BY T1.ID ) AS F ORDER BY F.IDFOR XML PATH 來串接字串時,利用 counts 欄位來決定是用 OR 或是 AND 來當連結,串接後再把第一個連結給拿掉。
- 參考 Solution 後的修正
DECLARE @t TABLE( ID INT, NAME VARCHAR(MAX) ) INSERT INTO @t (ID,[NAME]) SELECT 1, 'Deepak Kumar Goyal' INSERT INTO @t (ID,[NAME]) SELECT 2, 'Niladri Biswas' INSERT INTO @t (ID,[NAME]) SELECT 2, 'Pratik Shaw' INSERT INTO @t (ID,[NAME]) SELECT 3, 'Sumi Girijan' INSERT INTO @t (ID,[NAME]) SELECT 3, 'Suresh Beldar' INSERT INTO @t (ID,[NAME]) SELECT 3, 'Jeeva Baby' INSERT INTO @t (ID,[NAME]) SELECT 3, '' SELECT T.ID , CASE WHEN T.counts = 2 THEN REPLACE(T.[Name],',',' OR ') WHEN T.counts > 2 THEN REPLACE(T.[Name],',',' AND ') ELSE T.[Name] END AS [Name] FROM ( SELECT T1.ID , COUNT(T1.ID) AS counts, STUFF ( ( SELECT ',' + T2.[Name] FROM @t AS T2 WHERE T1.ID = T2.ID AND LEN(T2.Name) > 0 FOR XML PATH('') ) , 1 , 1 , '' ) AS [Name] FROM @t AS T1 WHERE LEN(Name) > 0 GROUP BY T1.ID ) AS T同樣利用 FOR XML PATH 串接,但是先用逗號來當連接,串接完後再根據 counts 來判斷,看連接是要用 AND 或 OR來取代逗號。
沒有留言:
張貼留言