数据库:我如何排序GUID

本文关键字:排序 GUID 何排序 数据库 | 更新日期: 2023-09-27 18:11:43

我的主键使用guid。

如何对GUID进行排序?

如果我创建一个datetime列并记录一个datetime戳,然后我可以按datetime排序呢?这是最好的方法吗?或者有更好的方法吗?

数据库:我如何排序GUID

SELECT * 
FROM myTable
ORDER BY CAST(myGuid AS VARCHAR(36))

Guid顾名思义就是唯一标识符。同一性并不意味着顺序,它只是给你一种方法来确定两个东西是否应该是相同的。为了排序,您需要确定比其他东西大或小意味着什么。从你的问题来看,排序似乎应该基于创建时间;指南不会帮你的。

死灵。
guid只是随机数,其中没有顺序性(除非您使用sequentialuid -但它会在计算机重启后重新启动,所以它几乎没有意义)。
下面是guid的实际排序方式:
代码不言自明,神奇的部分是:

System.Guid g
g.ToByteArray();
int[] m_byteOrder = new int[16] // 16 Bytes = 128 Bit 
    {10, 11, 12, 13, 14, 15, 8, 9, 6, 7, 4, 5, 0, 1, 2, 3};

public int Compare(Guid x, Guid y)
{
    byte byte1, byte2;
    //Swap to the correct order to be compared
    for (int i = 0; i < NUM_BYTES_IN_GUID; i++)
    {
        byte1 = x.ToByteArray()[m_byteOrder[i]];
        byte2 = y.ToByteArray()[m_byteOrder[i]];
        if (byte1 != byte2)
            return (byte1 < byte2) ? (int)EComparison.LT : (int)EComparison.GT;
    } // Next i 
    return (int)EComparison.EQ;
}

完整代码:

namespace BlueMine.Data
{

    public class SqlGuid
        : System.IComparable
        , System.IComparable<SqlGuid>
        , System.Collections.Generic.IComparer<SqlGuid>
        , System.IEquatable<SqlGuid>
    {
        private const int NUM_BYTES_IN_GUID = 16;
        // Comparison orders.
        private static readonly int[] m_byteOrder = new int[16] // 16 Bytes = 128 Bit 
        {10, 11, 12, 13, 14, 15, 8, 9, 6, 7, 4, 5, 0, 1, 2, 3};
        private byte[] m_bytes; // the SqlGuid is null if m_value is null

        public SqlGuid(byte[] guidBytes)
        {
            if (guidBytes == null || guidBytes.Length != NUM_BYTES_IN_GUID)
                throw new System.ArgumentException("Invalid array size");
            m_bytes = new byte[NUM_BYTES_IN_GUID];
            guidBytes.CopyTo(m_bytes, 0);
        }

        public SqlGuid(System.Guid g)
        {
            m_bytes = g.ToByteArray();
        }

        public byte[] ToByteArray()
        {
            byte[] ret = new byte[NUM_BYTES_IN_GUID];
            m_bytes.CopyTo(ret, 0);
            return ret;
        }
        int CompareTo(object obj)
        {
            if (obj == null)
                return 1; // https://msdn.microsoft.com/en-us/library/system.icomparable.compareto(v=vs.110).aspx
            System.Type t = obj.GetType();
            if (object.ReferenceEquals(t, typeof(System.DBNull)))
                return 1;
            if (object.ReferenceEquals(t, typeof(SqlGuid)))
            {
                SqlGuid ui = (SqlGuid)obj;
                return this.Compare(this, ui);
            } // End if (object.ReferenceEquals(t, typeof(UInt128)))
            return 1;
        } // End Function CompareTo(object obj)

        int System.IComparable.CompareTo(object obj)
        {
            return this.CompareTo(obj);
        }

        int CompareTo(SqlGuid other)
        {
            return this.Compare(this, other);
        }

        int System.IComparable<SqlGuid>.CompareTo(SqlGuid other)
        {
            return this.Compare(this, other);
        }

        enum EComparison : int
        {
            LT = -1, // itemA precedes itemB in the sort order.
            EQ = 0, // itemA occurs in the same position as itemB in the sort order.
            GT = 1 // itemA follows itemB in the sort order.
        }

        public int Compare(SqlGuid x, SqlGuid y)
        {
            byte byte1, byte2;
            //Swap to the correct order to be compared
            for (int i = 0; i < NUM_BYTES_IN_GUID; i++)
            {
                byte1 = x.m_bytes[m_byteOrder[i]];
                byte2 = y.m_bytes[m_byteOrder[i]];
                if (byte1 != byte2)
                    return (byte1 < byte2) ? (int)EComparison.LT : (int)EComparison.GT;
            } // Next i 
            return (int)EComparison.EQ;
        }

        int System.Collections.Generic.IComparer<SqlGuid>.Compare(SqlGuid x, SqlGuid y)
        {
            return this.Compare(x, y);
        }

        public bool Equals(SqlGuid other)
        {
            return Compare(this, other) == 0;
        }

        bool System.IEquatable<SqlGuid>.Equals(SqlGuid other)
        {
            return this.Equals(other);
        }

    }

}

我将使用int(或bigint)列作为标识。每次插入一行时,标识将增加。您可以对该列进行排序,以按照插入的顺序获得行。

你想干什么?按插入日期排序?为此,您确实需要一个datetime(或其变体之一)字段,因为guids和auto incr键都不能保证顺序,只能保证唯一性

主键排序