如何在 SQL Server 中生成 id 以便轻松排序?

发布于 2024-09-07 05:35:37 字数 380 浏览 5 评论 0原文

我正在制作一个网站,但在生成父/子树时遇到问题,例如:

Page 1
---Sub page 1
------Sub page 1 - 1
Page 2
Page 3
---Sub page 3
------Sub page 3 - 1
------Sub page 3 - 2

如果我使用 UID,则不可能编写“ORDER BY”t-sql 来创建树。我正在考虑一个可以生成 ID (varchar) 的函数,例如:

001000000
---001001000
------001001001
002000000
003000000
---003001000
------003001001
------003001002

I'm making an website and I have problem generate the parent/child tree like:

Page 1
---Sub page 1
------Sub page 1 - 1
Page 2
Page 3
---Sub page 3
------Sub page 3 - 1
------Sub page 3 - 2

If I use UID, it's impossible to write the "ORDER BY" t-sql to make the tree. I'm thinking of a function that can generate the ID (varchar) such as:

001000000
---001001000
------001001001
002000000
003000000
---003001000
------003001001
------003001002

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

擦肩而过的背影 2024-09-14 05:35:37

我会跳过自定义 ID 并将父/子关系存储在数据库中。然后使用递归查询来构建树。

I would skip the custom Id and store parent/child relationships in the database. Then use a recursive query to build your tree.

淡紫姑娘! 2024-09-14 05:35:37

查看层次结构的嵌套集合模型。 Joe Celko 有一本书,除了介绍树建模的其他方法外,还介绍了这一点以及 SQL 中的层次结构。使用嵌套集合模型,您将得到如下所示的结果:

CREATE TABLE Tree_Nodes
(
    lft     INT         NOT NULL,
    rgt     INT         NOT NULL,
    name    VARCHAR(40) NOT NULL,
    CONSTRAINT PK_Tree_Nodes PRIMARY KEY CLUSTERED (lft, rgt)
)
INSERT INTO Tree_Nodes (lft, rgt, name)
SELECT 1, 6, 'Page 1' UNION ALL
SELECT 2, 5, 'Sub page 1' UNION ALL
SELECT 3, 4, 'Sub page 1 - 1' UNION ALL
SELECT 7, 8, 'Page 2' UNION ALL
SELECT 9, 16, 'Page 3' UNION ALL
SELECT 10, 15, 'Sub page 3' UNION ALL
SELECT 11, 12, 'Sub page 3 - 1' UNION ALL
SELECT 13, 14, 'Sub page 3 - 2'

然后,要获得您想要获得的结果,只需:

SELECT
    lft,
    rgt,
    name
FROM
    Tree_Nodes
ORDER BY
    lft

Look into the nested set model for hierarchies. Joe Celko has a book which covers this in addition to other ways to model trees and hierarchies in SQL. With the nested set model you would have something like this:

CREATE TABLE Tree_Nodes
(
    lft     INT         NOT NULL,
    rgt     INT         NOT NULL,
    name    VARCHAR(40) NOT NULL,
    CONSTRAINT PK_Tree_Nodes PRIMARY KEY CLUSTERED (lft, rgt)
)
INSERT INTO Tree_Nodes (lft, rgt, name)
SELECT 1, 6, 'Page 1' UNION ALL
SELECT 2, 5, 'Sub page 1' UNION ALL
SELECT 3, 4, 'Sub page 1 - 1' UNION ALL
SELECT 7, 8, 'Page 2' UNION ALL
SELECT 9, 16, 'Page 3' UNION ALL
SELECT 10, 15, 'Sub page 3' UNION ALL
SELECT 11, 12, 'Sub page 3 - 1' UNION ALL
SELECT 13, 14, 'Sub page 3 - 2'

Then to get the result that you're trying to get, it's simply:

SELECT
    lft,
    rgt,
    name
FROM
    Tree_Nodes
ORDER BY
    lft
把时间冻结 2024-09-14 05:35:37

对于网页,使用 URL 很简单。托比的想法也不错,但它可能比你需要的更复杂(尽管我实际上在另一个应用程序中按照他告诉你的去做,所以在正确的情况下我不会拒绝它)。你的计划实际上也会奏效。

但是,为什么您需要一个函数来为您做这件事呢?在扁平化的方案中,您可以很乐意让 AUTO_INCRMENT 为您完成工作;但在层次结构中,您想要决定事物的走向,但没有任何函数可以为您做这件事。

For web-pages, it's straightforward to use the URL for this. Toby's idea is also okay, but it is probably more complicated than you need (although I am actually doing what he's telling you to, in another application, so I'm not dissing it, in right circumstances). Your scheme would actually work, too.

However, why would you want a function to do it for you? In a flat scheme of things, you can be happy to let AUTO_INCREMENT do your work for you; but in a hierarchy you want to decide where things go, and no function can do it for you.

っ〆星空下的拥抱 2024-09-14 05:35:37

也许您可以将父 ID 存储在表中,而不是尝试在表中执行此操作,只需返回行并使用递归来构建树,如下所示,为了在第一次运行后进行优化,您可以存储 Tab 键顺序以及您在数据类中第一次递归运行时分配的属性中的排序顺序。这是一个例子...

class Program
{


    static void Main(string[] args)
    {
        Program program = new Program();

        List<Data> rows = new List<Data>();
        program.CreateData(rows);

        Console.WriteLine("Data ...");
        program.ShowData(rows);
        Console.WriteLine("");

        Console.WriteLine("Data as tree ...");
        program.ShowDataAsTree(rows);
        Console.WriteLine("");

    }


    public void ShowData(List<Data> rows)
    {
        foreach (Data row in rows)
        {
            Data parent = rows.Find(item => item.Id == row.Parent);
            Console.WriteLine(String.Format("Name = {0}, Parents Name = {1}", row.Text, parent == null ? "" : parent.Text));
        }
    }

    public void ShowDataAsTree(List<Data> rows)
    {
        rows.Sort((item1, item2) => item1.Text.CompareTo(item2.Text));
        ShowDataSortedWrk(rows, Guid.Empty, 0);
    }

    public void ShowDataSortedWrk(List<Data> rows, Guid parentId, int tab)
    {
        foreach (Data row in rows)
        {
            if (row.Parent == parentId)
            {
                for (int i = 0; i < tab; i++)
                {
                    Console.Write("\t");
                }

                Console.WriteLine(row.Text);

                ShowDataSortedWrk(rows, row.Id, tab + 1);
            }
        }
    }

    public void CreateData(List<Data> rows)
    {
        Data alice = new Data(Guid.Empty, "Alice");
        rows.Add(alice);

        Data eric = new Data(Guid.Empty, "Eric");
        rows.Add(eric);

        Data mike = new Data(alice.Id, "Mike");
        rows.Add(mike);

        rows.Add(new Data(mike.Id, "Mark"));
        rows.Add(new Data(eric.Id, "Jane"));
        rows.Add(new Data(alice.Id, "Emma"));
        rows.Add(new Data(mike.Id, "Fred"));
        rows.Add(new Data(alice.Id, "Perry"));
        rows.Add(new Data(eric.Id, "Julie"));
        rows.Add(new Data(eric.Id, "Paul"));
    }
}

public class Data
{
    public Data(Guid parent, string text)
    {
        this.Id = Guid.NewGuid();
        this.Parent = parent;
        this.Text = text;
    }

    public Guid Id
    {
        get;
        set;
    }


    public Guid Parent
    {
        get;
        set;
    }


    public String Text
    {
        get;
        set;
    }
}

Maybe you can store the parent id in the table and instead of trying to do this in the table, simply return the rows and use recursion to build you're tree as follows, for optimization after the first run, you could store the tab order and the sort order in a property you assign on the first recursive run in you're data class. Here is an example...

class Program
{


    static void Main(string[] args)
    {
        Program program = new Program();

        List<Data> rows = new List<Data>();
        program.CreateData(rows);

        Console.WriteLine("Data ...");
        program.ShowData(rows);
        Console.WriteLine("");

        Console.WriteLine("Data as tree ...");
        program.ShowDataAsTree(rows);
        Console.WriteLine("");

    }


    public void ShowData(List<Data> rows)
    {
        foreach (Data row in rows)
        {
            Data parent = rows.Find(item => item.Id == row.Parent);
            Console.WriteLine(String.Format("Name = {0}, Parents Name = {1}", row.Text, parent == null ? "" : parent.Text));
        }
    }

    public void ShowDataAsTree(List<Data> rows)
    {
        rows.Sort((item1, item2) => item1.Text.CompareTo(item2.Text));
        ShowDataSortedWrk(rows, Guid.Empty, 0);
    }

    public void ShowDataSortedWrk(List<Data> rows, Guid parentId, int tab)
    {
        foreach (Data row in rows)
        {
            if (row.Parent == parentId)
            {
                for (int i = 0; i < tab; i++)
                {
                    Console.Write("\t");
                }

                Console.WriteLine(row.Text);

                ShowDataSortedWrk(rows, row.Id, tab + 1);
            }
        }
    }

    public void CreateData(List<Data> rows)
    {
        Data alice = new Data(Guid.Empty, "Alice");
        rows.Add(alice);

        Data eric = new Data(Guid.Empty, "Eric");
        rows.Add(eric);

        Data mike = new Data(alice.Id, "Mike");
        rows.Add(mike);

        rows.Add(new Data(mike.Id, "Mark"));
        rows.Add(new Data(eric.Id, "Jane"));
        rows.Add(new Data(alice.Id, "Emma"));
        rows.Add(new Data(mike.Id, "Fred"));
        rows.Add(new Data(alice.Id, "Perry"));
        rows.Add(new Data(eric.Id, "Julie"));
        rows.Add(new Data(eric.Id, "Paul"));
    }
}

public class Data
{
    public Data(Guid parent, string text)
    {
        this.Id = Guid.NewGuid();
        this.Parent = parent;
        this.Text = text;
    }

    public Guid Id
    {
        get;
        set;
    }


    public Guid Parent
    {
        get;
        set;
    }


    public String Text
    {
        get;
        set;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文