code_junkie

Is there a way to create a SQL Server function to “join” multiple rows from a subquery into a single delimited field?

Nov 10th, 2011
127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.68 KB | None | 0 0
  1. VehicleID Name
  2. 1 Chuck
  3. 2 Larry
  4.  
  5. LocationID VehicleID City
  6. 1 1 New York
  7. 2 1 Seattle
  8. 3 1 Vancouver
  9. 4 2 Los Angeles
  10. 5 2 Houston
  11.  
  12. VehicleID Name Locations
  13. 1 Chuck New York, Seattle, Vancouver
  14. 2 Larry Los Angeles, Houston
  15.  
  16. DECLARE @VehicleID int
  17. DECLARE @VehicleName varchar(100)
  18. DECLARE @LocationCity varchar(100)
  19. DECLARE @Locations varchar(4000)
  20. DECLARE @Results TABLE
  21. (
  22. VehicleID int
  23. Name varchar(100)
  24. Locations varchar(4000)
  25. )
  26.  
  27. DECLARE VehiclesCursor CURSOR FOR
  28. SELECT
  29. [VehicleID]
  30. , [Name]
  31. FROM [Vehicles]
  32.  
  33. OPEN VehiclesCursor
  34.  
  35. FETCH NEXT FROM VehiclesCursor INTO
  36. @VehicleID
  37. , @VehicleName
  38. WHILE @@FETCH_STATUS = 0
  39. BEGIN
  40.  
  41. SET @Locations = ''
  42.  
  43. DECLARE LocationsCursor CURSOR FOR
  44. SELECT
  45. [City]
  46. FROM [Locations]
  47. WHERE [VehicleID] = @VehicleID
  48.  
  49. OPEN LocationsCursor
  50.  
  51. FETCH NEXT FROM LocationsCursor INTO
  52. @LocationCity
  53. WHILE @@FETCH_STATUS = 0
  54. BEGIN
  55. SET @Locations = @Locations + @LocationCity
  56.  
  57. FETCH NEXT FROM LocationsCursor INTO
  58. @LocationCity
  59. END
  60. CLOSE LocationsCursor
  61. DEALLOCATE LocationsCursor
  62.  
  63. INSERT INTO @Results (VehicleID, Name, Locations) SELECT @VehicleID, @Name, @Locations
  64.  
  65. END
  66. CLOSE VehiclesCursor
  67. DEALLOCATE VehiclesCursor
  68.  
  69. SELECT * FROM @Results
  70.  
  71. SELECT VehicleID
  72. , Name
  73. , JOIN(SELECT City FROM Locations WHERE VehicleID = Vehicles.VehicleID, ', ') AS Locations
  74. FROM Vehicles
  75.  
  76. SELECT [VehicleID]
  77. , [Name]
  78. , (SELECT CAST(City + ', ' AS VARCHAR(MAX))
  79. FROM [Location]
  80. WHERE (VehicleID = Vehicle.VehicleID)
  81. FOR XML PATH ('')
  82. ) AS Locations
  83. FROM [Vehicle]
  84.  
  85. DECLARE @EmployeeList varchar(100)
  86. SELECT @EmployeeList = COALESCE(@EmployeeList + ', ', '') +
  87. CAST(EmpUniqueID AS varchar(5))
  88. FROM SalesCallsEmployees
  89. WHERE SalCal_UniqueID = 1
  90.  
  91. CREATE FUNCTION fnConcatVehicleCities(@VehicleId SMALLINT)
  92. RETURNS VARCHAR(1000) AS
  93. BEGIN
  94. DECLARE @csvCities VARCHAR(1000)
  95. SELECT @csvCities = COALESCE(@csvCities + ', ', '') + COALESCE(City,'')
  96. FROM Vehicles
  97. WHERE VehicleId = @VehicleId
  98. return @csvCities
  99. END
  100.  
  101. -- //Once the User defined function is created then run the below sql
  102.  
  103. SELECT VehicleID
  104. , dbo.fnConcatVehicleCities(VehicleId) AS Locations
  105. FROM Vehicles
  106. GROUP BY VehicleID
  107.  
  108. stuff(
  109. (select ',' + Column
  110. from Table
  111. inner where inner.Id = outer.Id
  112. for xml path('')
  113. ), 1,1,'') as Values
  114.  
  115. SELECT [VehicleID]
  116. , [Name]
  117. , [Locations] = Isnull( Stuff(
  118. ( SELECT N', ' + [City] FROM [Locations]
  119. WHERE VehicleID = a.VehicleID
  120. FOR XML PATH(''),TYPE ).value('text()[1]', 'nvarchar(max)')
  121. , 1, 2, N''), N'')
  122. FROM [Vehicle] a
  123.  
  124. SELECT SUM(column)
  125. SELECT AVG(column)
  126. SELECT STDEV(column)
  127.  
  128. SELECT CONCAT(column, ', ')
  129.  
  130. change: this.intermediateResult.Append(value.Value).Append(',');
  131. to: this.intermediateResult.Append(value.Value);
  132.  
  133. change: output = this.intermediateResult.ToString(0, this.intermediateResult.Length - 1);
  134. to: output = this.intermediateResult.ToString();
  135.  
  136. SELECT dbo.CONCATENATE(column1 + '|') from table1
  137.  
  138. -- rank locations by incrementing lexicographical order
  139. WITH RankedLocations AS (
  140. SELECT
  141. VehicleID,
  142. City,
  143. ROW_NUMBER() OVER (
  144. PARTITION BY VehicleID
  145. ORDER BY City
  146. ) Rank
  147. FROM
  148. Locations
  149. ),
  150. -- concatenate locations using a recursive query
  151. -- (Common Table Expression)
  152. Concatenations AS (
  153. -- for each vehicle, select the first location
  154. SELECT
  155. VehicleID,
  156. CONVERT(nvarchar(MAX), City) Cities,
  157. Rank
  158. FROM
  159. RankedLocations
  160. WHERE
  161. Rank = 1
  162.  
  163. -- then incrementally concatenate with the next location
  164. -- this will return intermediate concatenations that will be
  165. -- filtered out later on
  166. UNION ALL
  167.  
  168. SELECT
  169. c.VehicleID,
  170. (c.Cities + ', ' + l.City) Cities,
  171. l.Rank
  172. FROM
  173. Concatenations c -- this is a recursion!
  174. INNER JOIN RankedLocations l ON
  175. l.VehicleID = c.VehicleID
  176. AND l.Rank = c.Rank + 1
  177. ),
  178. -- rank concatenation results by decrementing length
  179. -- (rank 1 will always be for the longest concatenation)
  180. RankedConcatenations AS (
  181. SELECT
  182. VehicleID,
  183. Cities,
  184. ROW_NUMBER() OVER (
  185. PARTITION BY VehicleID
  186. ORDER BY Rank DESC
  187. ) Rank
  188. FROM
  189. Concatenations
  190. )
  191. -- main query
  192. SELECT
  193. v.VehicleID,
  194. v.Name,
  195. c.Cities
  196. FROM
  197. Vehicles v
  198. INNER JOIN RankedConcatenations c ON
  199. c.VehicleID = v.VehicleID
  200. AND c.Rank = 1
  201.  
  202. using System;
  203. using System.Data;
  204. using System.Data.SqlClient;
  205. using System.Data.SqlTypes;
  206. using System.Text;
  207. using Microsoft.SqlServer.Server;
  208. [Serializable]
  209. [Microsoft.SqlServer.Server.SqlUserDefinedAggregate(Format.UserDefined,MaxByteSize=8000)]
  210. public class CSV:IBinarySerialize
  211. {
  212. private StringBuilder Result;
  213. public void Init() {
  214. this.Result = new StringBuilder();
  215. }
  216.  
  217. public void Accumulate(SqlString Value) {
  218. if (Value.IsNull) return;
  219. this.Result.Append(Value.Value).Append(",");
  220. }
  221. public void Merge(CSV Group) {
  222. this.Result.Append(Group.Result);
  223. }
  224. public SqlString Terminate() {
  225. return new SqlString(this.Result.ToString());
  226. }
  227. public void Read(System.IO.BinaryReader r) {
  228. this.Result = new StringBuilder(r.ReadString());
  229. }
  230. public void Write(System.IO.BinaryWriter w) {
  231. w.Write(this.Result.ToString());
  232. }
  233. }
  234.  
  235. CREATE FUNCTION [dbo].[JoinTexts]
  236. (
  237. @delimiter VARCHAR(20) ,
  238. @whereClause VARCHAR(1)
  239. )
  240. RETURNS VARCHAR(MAX)
  241. AS
  242. BEGIN
  243. DECLARE @Texts VARCHAR(MAX)
  244.  
  245. SELECT @Texts = COALESCE(@Texts + @delimiter, '') + T.Texto
  246. FROM SomeTable AS T
  247. WHERE T.SomeOtherColumn = @whereClause
  248.  
  249. RETURN @Texts
  250. END
  251. GO
  252.  
  253. SELECT dbo.JoinTexts(' , ', 'Y')
Add Comment
Please, Sign In to add comment