A Sql Stumper

无意中发现Joe Celko 在http://www.simple-talk.com/sql/t-sql-programming/celkos-sql-stumper-the-class-scheduling-problem/ post了一个问题。然后有在http://weblogs.sqlteam.com/peterl/archive/2010/01/23/Celko-Stumper---The-Class-Scheduling-Problem.aspx 发现一种解决方案。于是乎自己也弄了2个解决方案。

方案1:使用cursor,这种方式最简单,典型的过程式解决方案:

DECLARE @classstate TABLE(

	room_nbr CHAR(2) PRIMARY KEY,

	class_nbr CHAR(2)

)



DECLARE @roomnbr AS CHAR(2)

DECLARE @roomz AS INT



DECLARE room_cursor CURSOR FOR

	SELECT room_nbr, room_size

	FROM Rooms

	ORDER BY room_size DESC



OPEN room_cursor

FETCH NEXT FROM room_cursor INTO @roomnbr, @roomz



WHILE @@FETCH_STATUS = 0

BEGIN 

	DECLARE @classnbr AS CHAR(2)

	SET @classnbr = null

	SELECT TOP 1 @classnbr = class_nbr

	FROM Classes c

	WHERE @roomz > class_size AND c.class_nbr NOT IN(

		SELECT class_nbr

		FROM @classstate)



	IF @classnbr IS NOT NULL

		INSERT INTO @classstate VALUES(@roomnbr,

			@classnbr)

	

	FETCH NEXT FROM room_cursor INTO @roomnbr, @roomz	

END



CLOSE room_cursor

DEALLOCATE room_cursor



SELECT c.*, r.*

FROM Classes c 

JOIN @classstate m ON c.class_nbr = m.class_nbr

JOIN Rooms r ON m.room_nbr = r.room_nbr

ORDER BY c.class_nbr, r.room_nbr

方案2:大家看看,有问题指出来:

DECLARE @source TABLE(

	room_nbr CHAR(2),

	room_size int,

	class_nbr CHAR(2),

	class_size int,

	recID INT IDENTITY(1, 1) PRIMARY KEY CLUSTERED)

	

INSERT @source(room_nbr, room_size, class_nbr,class_size)

SELECT r.room_nbr, r.room_size, c.class_nbr, c.class_size

FROM dbo.Rooms r

INNER JOIN dbo.Classes c

ON c.class_size <= r.room_size

ORDER BY r.room_size DESC, c.class_size DESC



;with cte1(rn, rs, cn, cs) as(

	SELECT room_nbr, room_size, class_nbr, class_size

	FROM @source

	WHERE recID = 1

	

	UNION ALL

	

	SELECT D.room_nbr, D.room_size, D.class_nbr, D.class_size

	FROM

	(

		SELECT s2.room_nbr, s2.room_size, s2.class_nbr, s2.class_size

		FROM @source s2 JOIN cte1 c ON s2.room_size < c.rs AND

			s2.room_nbr <> c.rn AND s2.class_nbr <> c.cn

	) as D

)



SELECT d2.rn, d2.rs, d2.cn, d2.cs

FROM(

SELECT c.rn, c.rs, c.cn, c.cs, ROW_NUMBER() OVER(PARTITION BY c.rn ORDER BY c.cn) AS cc

FROM cte1  c JOIN(

	SELECT rn, MAX(cs) as m

	FROM cte1

	GROUP BY rn) d

	ON c.rn =d.rn and c.cs = d.m) d2

WHERE d2.cc = 1

ORDER BY rs DESC

你可能感兴趣的:(sql)