如何形成树图,使速度更慢的SQL更快

时间:2016-10-24 23:54:10

标签: sql dictionary sql-server-2012 tree

如何用sql形成树。 我找不到用sql形成树的好方法如下。

  1. 树由位置组成。
  2. 每个位置都有3个数字  自己的号码  号码
     序号
  3. 最高职位只有一个。
  4. 每个职位都有唯一的编号。
  5. 每个位置都链接其他位置。
     从UP到DOWN,上升号码
     e.g
     4个位置树的情况

     00002 - 自己的号码  00001 - 向上号码      1 - 序号


     00003 - 自己的号码  00001 - 向上号码      2 - 序列号

     00004 - 自己的号码  00002 - 向上号码      1 - 序号

      00001
      00002 00003
      00004

  6. UP位置是所有DOWN位置的中心。
  7. 每个职位都可以有多个职位。
  8. 每个职位都不与其他职位重叠。
  9. 没有差距。
  10. 位置的
      身高 - 80
      宽度 - 80
     职位之间 - 20
  11. 顶部位置
     x轴 - 0
     y轴 - 0

    我们有20万个职位 虽然我们想在30秒内形成一棵树,但我们最好的记录是5小时!
    你能帮助我们吗?请。

    非常感谢你。

    https://lh6.googleusercontent.com/FIkn7yIVKozIL9S5XZFyn_S0YL2NBnFf-9j4PwQOW7CjmTXXXvxpOG4OEUXlTPbm0Th7uTKsR7QxfjY=w1367-h727-rw



  12. 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 */
    

0 个答案:

没有答案