如何用sql形成树。
我找不到用sql形成树的好方法如下。
sqlserver 2012的源代码
/* start */
IF object_id('WEBTreeMap') IS not NULL DROP TABLE WEBTreeMap;
CREATE TABLE [dbo].[WEBTreeMap](
[IDNO] [char](10) NOT NULL,
[Eda] [char](3) NOT NULL,
[UPIDNO] [varchar](10) NOT NULL,
[UPEda] [varchar](3) NOT NULL,
[MapLimitLV_1] [int] NOT NULL,
[MapLimitFG_1] [int] NOT NULL,
[DownPossession] [bit] NOT NULL,
CONSTRAINT [PK__WEBTreeMap__29A60B9828B2E0D5] PRIMARY KEY CLUSTERED
(
[IDNO] ASC,
[Eda] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
;
/* insert sample */
INSERT INTO WEBTreeMap
SELECT '0000000001' as IDNO, '001' AS Eda, '' AS UPIDNO, '' AS UPEda, 0 AS MapLimitLV_1, 0 AS MapLimitFG_1, 'true' AS DownPossession UNION ALL
SELECT '0000000001' as IDNO, '002' AS Eda, '0000000001' AS UPIDNO, '001' AS UPEda, 0 AS MapLimitLV_1, 0 AS MapLimitFG_1, 'true' AS DownPossession UNION ALL
SELECT '0000000001' as IDNO, '003' AS Eda, '0000000001' AS UPIDNO, '001' AS UPEda, 0 AS MapLimitLV_1, 0 AS MapLimitFG_1, 'true' AS DownPossession UNION ALL
SELECT '0000000001' as IDNO, '004' AS Eda, '0000000001' AS UPIDNO, '002' AS UPEda, 0 AS MapLimitLV_1, 0 AS MapLimitFG_1, 'true' AS DownPossession UNION ALL
SELECT '0000000001' as IDNO, '005' AS Eda, '0000000001' AS UPIDNO, '003' AS UPEda, 0 AS MapLimitLV_1, 0 AS MapLimitFG_1, 'true' AS DownPossession
;
IF object_id('WEBTreeMap_2') IS not NULL DROP TABLE WEBTreeMap_2;
CREATE TABLE [dbo].[WEBTreeMap_2](
[TopIDNO] [varchar](10) NOT NULL,
[TopEda] [varchar](3) NOT NULL,
[IDNO] [varchar](50) NOT NULL,
[Eda] [varchar](50) NOT NULL,
[Soshiki] [varchar](1) NOT NULL,
[LV] [int] NOT NULL,
[MapLimitFG] [int] NOT NULL,
[xaxis] [int] NOT NULL,
[yaxis] [int] NOT NULL,
[Team] [int] NOT NULL,
[TeamLeft] [int] NOT NULL,
[TeamRight] [int] NOT NULL,
[UPPosition] [varchar](13) NOT NULL,
[sequence1] [int] NOT NULL,
[MaxSequence] [int] NOT NULL,
[sequence2] [int] NOT NULL,
[SequenceNO] [int] NOT NULL,
[DownPossession] [bit] NOT NULL,
[LeftSpace] [int] NOT NULL,
[UPLeftSpace] [int] NOT NULL,
CONSTRAINT [PK_WEBTreeMap_2] PRIMARY KEY CLUSTERED
(
[TopIDNO] ASC,
[TopEda] ASC,
[IDNO] ASC,
[Eda] ASC,
[Soshiki] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
;
ALTER TABLE [dbo].[WEBTreeMap_2] ADD CONSTRAINT [DF_WEBTreeMap_2_SequenceNO] DEFAULT ((0)) FOR [SequenceNO]
;
DECLARE @IDNO varchar(10), @Eda varchar(3), @Seigenint int, @Soshiki varchar(1);
SELECT @IDNO = '0000000001', @Eda = '001', @Seigenint = 2000000, @Soshiki = '1';
UPDATE WEBTreeMap SET MapLimitLV_1 = 0 WHERE IDNO = @IDNO AND Eda = @Eda;
delete WEBTreeMap_2 WHERE TopIDNO = @IDNO AND TopEda = @Eda and Soshiki = @Soshiki;
DECLARE @LV int, @LVNinzu1LVMae int, @LVNinzu int;
SET @LV = 0;
SET @LVNinzu1LVMae = 0;
SET @LVNinzu = 0;
/* set Top */
INSERT INTO WEBTreeMap_2 (TopIDNO, TopEda, IDNO, Eda, Soshiki, LV, MapLimitFG, xaxis, yaxis, Team, TeamLeft, TeamRight, UPPosition, sequence1, MaxSequence, sequence2, SequenceNO, DownPossession, LeftSpace, UPLeftSpace)
SELECT IDNO, Eda, IDNO, Eda, @Soshiki, @LV, 0, 0, 0, 0, 0 AS TeamLeft, 0 AS TeamRight, '', 1, 1, 1, 1, DownPossession, 0, 0 FROM WEBTreeMap WHERE IDNO = @IDNO AND Eda = @Eda
;
WHILE @LVNinzu <= @Seigenint
BEGIN
SELECT @LVNinzu = COUNT(*) FROM WEBTreeMap_2 WHERE TopIDNO = @IDNO AND TopEda = @Eda AND Soshiki = @Soshiki;
print 'LV : ' + convert(varchar,@LV)
print '@LVNinzu : ' + convert(varchar,@LVNinzu)
print '@Seigenint : ' + convert(varchar,@Seigenint)
--UPDATE WEBTreeMap SET MapLimitLV_1 = @LV WHERE IDNO = @IDNO AND Eda = @Eda;
IF @LVNinzu >= @Seigenint BEGIN BREAK END;
SET @LV = @LV + 1;
INSERT INTO WEBTreeMap_2 (TopIDNO, TopEda, IDNO, Eda, Soshiki, LV, MapLimitFG, xaxis, yaxis, Team, TeamLeft, TeamRight, UPPosition, sequence1, MaxSequence, sequence2, DownPossession, LeftSpace, UPLeftSpace)
SELECT Jowy.TopIDNO, Jowy.TopEda, Kawy.IDNO, Kawy.Eda, @Soshiki, @LV, Kawy.MapLimitFG_1, Jowy.xaxis/* + ((80 + 20) * LeftSpace) */ AS xaxis, Jowy.yaxis + 110 + 20 AS yaxis, Jowy.xaxis/* + ((80 + 20) * LeftSpace) */ AS Team, Jowy.xaxis/* + ((80 + 20) * LeftSpace) */ AS TeamLeft, Jowy.xaxis/* + ((80 + 20) * LeftSpace) */ AS TeamRight
, (Jowy.IDNO + Jowy.Eda) AS UPPosition
, (ROW_NUMBER()OVER(PARTITION BY Jowy.IDNO, Jowy.Eda ORDER BY Kawy.IDNO, Kawy.Eda)) AS ren1, 0 AS MaxSequence
, (ROW_NUMBER()OVER(ORDER BY Jowy.xaxis /* ,Jowy.IDNO, Jowy.Eda */, Kawy.IDNO, Kawy.Eda)) AS ren2, Kawy.DownPossession AS DownPossession, 0 AS LeftSpace, Jowy.LeftSpace AS UPLeftSpace
FROM WEBTreeMap AS Kawy INNER JOIN WEBTreeMap_2 as Jowy ON Jowy.IDNO = Kawy.UPIDNO AND Jowy.Eda = Kawy.UPEda
AND Jowy.TopIDNO = @IDNO AND Jowy.TopEda = @Eda AND Soshiki = @Soshiki AND Jowy.LV = @LV - 1 AND Jowy.MapLimitFG = 0
;
IF @@ROWCOUNT = 0
BEGIN
UPDATE WEBTreeMap SET MapLimitLV_1 = 100 WHERE IDNO = @IDNO AND Eda = @Eda;
BREAK
END;
WITH t1 AS (
SELECT TopIDNO, TopEda, Soshiki, LV, Team, Max(sequence1) AS MaxRen
FROM WEBTreeMap_2
WHERE TopIDNO = @IDNO AND TopEda = @Eda AND Soshiki = @Soshiki AND LV = @LV
GROUP BY TopIDNO, TopEda, Soshiki, LV, Team
)
UPDATE WEBTreeMap_2 SET MaxSequence = MaxRen
FROM WEBTreeMap_2 AS w INNER JOIN t1 ON w.TopIDNO = t1.TopIDNO AND w.TopEda = t1.TopEda AND w.Soshiki = t1.Soshiki AND w.LV = t1.LV AND w.Team = t1.Team
;
/* gather left */
UPDATE WEBTreeMap_2 SET xaxis = Team + (((80 + 20) * ROUND((MaxSequence / 2),0)) * -1) + (CASE (MaxSequence % 2) WHEN 0 THEN + ((80 / 2) + (20 / 2)) ELSE 0 END)
WHERE TopIDNO = @IDNO AND TopEda = @Eda AND Soshiki = @Soshiki AND LV = @LV AND MaxSequence > 1 /* AND sequence1 = 1 */
;
/*
SELECT TopIDNO, TopEda, Soshiki, LV, Team, (((80 + 20) * ROUND((MaxSequence / 2),0)) * -1) - (CASE (MaxSequence % 2) WHEN 0 THEN + ((80 / 2) + (20 / 2)) ELSE 0 END)
FROM WEBTreeMap_2
WHERE TopIDNO = @IDNO AND TopEda = @Eda AND Soshiki = @Soshiki AND LV = @LV AND sequence1 = 1
*/
/* spread */
UPDATE WEBTreeMap_2 SET TeamLeft = xaxis, xaxis = xaxis + ((80 + 20) * (sequence1 - 1))
WHERE TopIDNO = @IDNO AND TopEda = @Eda AND Soshiki = @Soshiki AND LV = @LV
;
WITH t1 AS (
SELECT TopIDNO, TopEda, Soshiki, LV, Team, MAX(xaxis) AS MaxX
FROM WEBTreeMap_2
WHERE TopIDNO = @IDNO AND TopEda = @Eda AND Soshiki = @Soshiki AND LV = @LV
GROUP BY TopIDNO, TopEda, Soshiki, LV, Team
)
UPDATE WEBTreeMap_2 SET TeamRight = MaxX
FROM WEBTreeMap_2 AS w INNER JOIN t1 ON w.TopIDNO = t1.TopIDNO AND w.TopEda = t1.TopEda AND w.Soshiki = t1.Soshiki AND w.LV = t1.LV AND w.Team = t1.Team
/* WHERE TopIDNO = @IDNO AND TopEda = @Eda AND Soshiki = @Soshiki AND LV = @LV */
;
/* move each team */
IF object_id('tempdb..#Team') IS not NULL DROP TABLE #Team;
SELECT * INTO #Team FROM (
SELECT TopIDNO, TopEda, Soshiki, LV, ROW_NUMBER()OVER(ORDER BY Team) AS TeamNO, Team, TeamLeft, TeamRight
FROM WEBTreeMap_2
WHERE TopIDNO = @IDNO AND TopEda = @Eda AND Soshiki = @Soshiki AND LV = @LV
GROUP BY TopIDNO, TopEda, Soshiki, LV, Team, TeamLeft, TeamRight
) AS t
;
/*
select * from #Team
*/
DECLARE @MaxT int, @imaT int, @sa int, @TeamMei int;
SELECT @imaT = 1, @MaxT = (SELECT MAX(TeamNO) FROM #Team), @TeamMei = 0
;
WHILE @imaT <= @MaxT
BEGIN
SET @sa = 0;
SELECT @TeamMei = Team FROM #Team WHERE TeamNO = @imaT + 1;
SELECT @sa = (((SELECT TeamRight FROM #Team WHERE TeamNO = @imaT) + (80 + 20)) - (SELECT TeamLeft FROM #Team WHERE TeamNO = @imaT + 1))
IF @sa > 0
BEGIN
UPDATE #Team SET TeamLeft = TeamLeft + @sa, TeamRight = TeamRight + @sa WHERE TeamNO = @imaT + 1 /* TeamNO > @imaT */
UPDATE WEBTreeMap_2 SET xaxis = xaxis + @sa, TeamLeft = TeamLeft + @sa, TeamRight = TeamRight + @sa
FROM WEBTreeMap_2
WHERE TopIDNO = @IDNO AND TopEda = @Eda AND Soshiki = @Soshiki AND LV = @LV AND Team = @TeamMei
;
END;
SELECT @imaT = @imaT + 1;
END; /* WHILE @imaT <= @MaxT */
IF @LV >= 30 BREAK;
SET @LVNinzu1LVMae = @LVNinzu;
WITH R AS (
SELECT * FROM WEBTreeMap_2 WHERE TopIDNO = @IDNO AND TopEda = @Eda AND Soshiki = @Soshiki AND LV = @LV
)
, Aki AS (
SELECT R.IDNO, R.Eda, R.sequence2, MAX(L.sequence2) AS MaxRen
FROM WEBTreeMap_2 AS L INNER JOIN R ON R.TopIDNO = L.TopIDNO AND R.TopEda = L.TopEda AND R.Soshiki = L.Soshiki AND R.LV = L.LV
AND R.sequence2 > L.sequence2 AND L.DownPossession = 1
GROUP BY R.IDNO, R.Eda, R.sequence2
)
UPDATE WEBTreeMap_2 SET LeftSpace = (Aki.sequence2 - MaxRen) - 1
FROM WEBTreeMap_2 AS w INNER JOIN Aki ON w.TopIDNO = @IDNO AND w.TopEda = @Eda AND w.Soshiki = @Soshiki AND w.LV = @LV
AND w.IDNO = Aki.IDNO AND w.Eda = Aki.Eda
;
END; /* WHILE @LVNinzu <= @Seigenint */
UPDATE WEBTreeMap SET MapLimitLV_1 = @LV WHERE IDNO = @IDNO AND Eda = @Eda;
DECLARE @CntUpdate int;
SELECT @CntUpdate = 1;
WHILE @CntUpdate > 0
BEGIN
print '@CntUpdate : ' + convert(varchar,@CntUpdate)
SELECT @CntUpdate = 0;
/* UP is center of DOWNs */
IF object_id('tempdb..#UPMoving') IS not NULL DROP TABLE #UPMoving;
WITH t1 AS (
SELECT xaxis + (80 / 2) AS LeftEnd, LEFT(UPPosition,10) AS UPID, RIGHT(UPPosition,3) AS UPEda
FROM WEBTreeMap_2
WHERE TopIDNO = @IDNO AND TopEda = @Eda AND Soshiki = @Soshiki /* AND LV = @LV AND */ AND sequence1 = 1
), t2 AS (
SELECT xaxis + (80 / 2) AS RightEnd, LEFT(UPPosition,10) AS UPID, RIGHT(UPPosition,3) AS UPEda
FROM WEBTreeMap_2
WHERE TopIDNO = @IDNO AND TopEda = @Eda AND Soshiki = @Soshiki /* LV = @LV AND */ AND sequence1 = MaxSequence
)
SELECT * INTO #UPMoving FROM (
SELECT t1.UPID, t1. UPEda, (((t2.RightEnd + t1.LeftEnd) / 2) - (80 / 2)) AS UPaxis
--SELECT t1.UPID, t1. UPEda, (LeftEnd + (t2.RightEnd - t1.LeftEnd)) - (80 / 2) AS UPaxis
FROM t1 LEFT JOIN t2 ON t1.UPID = t2.UPID AND t1.UPEda = t2.UPEda
) AS oya
;
/*
select * from #UPMoving order by UPID
*/
UPDATE WEBTreeMap_2 SET xaxis = UPaxis
FROM WEBTreeMap_2 AS Jowy INNER JOIN #UPMoving AS Kawy ON Jowy.IDNO = Kawy.UPID AND Jowy.Eda = Kawy.UPEda AND Jowy.xaxis < Kawy.UPaxis
WHERE TopIDNO = @IDNO AND TopEda = @Eda AND Soshiki = @Soshiki /* AND LV = @LV */
;
SELECT @CntUpdate = @CntUpdate + @@ROWCOUNT;
SELECT @LV = @LV;
WHILE @@ROWCOUNT > 0
BEGIN
/* moving stray cats */
WITH L AS (
SELECT TopIDNO, TopEda, IDNO, Eda, Soshiki, LV, xaxis, Team, sequence2
FROM WEBTreeMap_2
WHERE TopIDNO = @IDNO AND TopEda = @Eda AND Soshiki = @Soshiki /* AND LV = @LV - 1 */
)
UPDATE WEBTreeMap_2 SET xaxis = L.xaxis + (80 + 20)
FROM WEBTreeMap_2 AS R INNER JOIN L ON L.TopIDNO = R.TopIDNO AND L.TopEda = R.TopEda AND L.Soshiki = R.Soshiki AND L.LV = R.LV AND
R.sequence2 = L.sequence2 + 1 AND R.xaxis < L.xaxis + (80 + 20) /* AND DownPossession = 0 */
;
--SELECT @CntUpdate = @CntUpdate + @@ROWCOUNT;
END; /* WHILE @@ROWCOUNT > 0 */
/* moving DOWNs based on UP position */
WITH Jowy AS (
SELECT (IDNO + Eda) AS uppos /*, UPPosition */, Jowy.xaxis, Jowy.xaxis - Kawy.UPaxis AS distance
FROM #UPMoving AS Kawy INNER JOIN WEBTreeMap_2 AS Jowy ON Jowy.IDNO = Kawy.UPID AND Jowy.Eda = Kawy.UPEda AND Jowy.xaxis > Kawy.UPaxis
WHERE TopIDNO = @IDNO AND TopEda = @Eda AND Soshiki = @Soshiki /* AND LV = @LV */
)
UPDATE WEBTreeMap_2 SET xaxis = Kawy.xaxis + distance
FROM WEBTreeMap_2 AS Kawy INNER JOIN Jowy ON Jowy.uppos = Kawy.UPPosition
WHERE TopIDNO = @IDNO AND TopEda = @Eda AND Soshiki = @Soshiki /* AND LV = @LV */
;
SELECT @CntUpdate = @CntUpdate + @@ROWCOUNT;
SELECT @LV = @LV;
WHILE @@ROWCOUNT > 0
BEGIN
/* moving stray cats */
WITH L AS (
SELECT TopIDNO, TopEda, IDNO, Eda, Soshiki, LV, xaxis, Team, sequence2
FROM WEBTreeMap_2
WHERE TopIDNO = @IDNO AND TopEda = @Eda AND Soshiki = @Soshiki /* AND LV = @LV - 1 */
)
UPDATE WEBTreeMap_2 SET xaxis = L.xaxis + (80 + 20)
FROM WEBTreeMap_2 AS R INNER JOIN L ON L.TopIDNO = R.TopIDNO AND L.TopEda = R.TopEda AND L.Soshiki = R.Soshiki AND L.LV = R.LV AND
R.sequence2 = L.sequence2 + 1 AND R.xaxis < L.xaxis + (80 + 20) /* AND DownPossession = 0 */
;
--SELECT @CntUpdate = @CntUpdate + @@ROWCOUNT;
END; /* WHILE @@ROWCOUNT > 0 */
END; /* WHILE @CntUpdate > 0 */
DECLARE @LeftMost int;
SELECT @LeftMost = MIN(xaxis) FROM WEBTreeMap_2 WHERE TopIDNO = @IDNO AND TopEda = @Eda AND Soshiki = @Soshiki
;
UPDATE WEBTreeMap_2 SET xaxis = xaxis + (@LeftMost * -1) WHERE TopIDNO = @IDNO AND TopEda = @Eda AND Soshiki = @Soshiki
;
UPDATE WEBTreeMap_2 SET SequenceNO = 1 WHERE sequence1 = 1 AND TopIDNO = @IDNO AND TopEda = @Eda AND Soshiki = @Soshiki
;
UPDATE WEBTreeMap_2 SET SequenceNO = 2 WHERE sequence1 = MaxSequence AND TopIDNO = @IDNO AND TopEda = @Eda AND Soshiki = @Soshiki
;
SELECT * FROM WEBTreeMap_2
;
/* end */