从相同的ID集生成相同的ID

时间:2013-10-29 10:18:29

标签: c# hash ssis

我有一个问题,我会尝试解释。我的想法是在C#中用SSIS创建一个脚本,然后为表中的每个唯一ID组合生成一个ID列表。

我有一个SQL服务器表,它由两列组成。列是ID(我可以将它们设为数字,但原始格式为字母数字字符串)。我想从第2列中连接到第1列的ID集合中生成新ID。

 Col1  Col2    Generated ID
   1     1
   1     2    => 1
   1     3
 -----------
   2     1    => 2
   2     3
 -----------
   3     3
   3     1    => 1
   3     2

我在想哈希函数可能吗?但是如何从1和3的集合中获取相同的ID?独立于秩序?我需要先对它们进行排序吗?

我需要“10点声望”才能发布图片,所以我希望我的插图可以解释这个问题......

2 个答案:

答案 0 :(得分:0)

作为尝试理解您的问题的更多示例,您是否希望Col2中的以下几组值返回喜欢'123'的内容作为下面列出的所有案例的“生成的ID”值,像这样?

Col2 =>生成的ID

1,2,3 => 123

1,3,2 => 123

2,1,3 => 123

2,3,1 => 123

3,1,2 => 123

3,2,1 => 123

如果是的话,那么基于上述假设并回答你的问题:

  • 是的,哈希函数可以执行
  • 如何获得相同的“生成的ID”第1组和第3组(在您的示例中)将取决于您的GetHashCode()覆盖/实现
  • 是的,您可能需要排序,但这又取决于您的实施。

由于您提到在SSIS中使用C#脚本,可能的C#实现可能是实现一个(非常!)简单的Hash类,它给出了一组Col2值(对于每个数据集),简单地说:

  1. 对Col2的值进行排序,以便按“正确”顺序获取它们
  2. 返回有序数据集的一些整数表示以获取Hash(例如,将int连接为字符串,然后转换回int)
  3. 哈希类可以在你的(base?)类的GetHashCode()函数中实例化,该函数传递Col2值并执行上面的步骤(1)和(2),根据需要返回哈希码。

    这样的事情可能对您有用(假设您可以访问您正在使用的.NET版本中的Generics):

    namespace SimpleHashNamespace
    {
        public class SimpleHash
        {
            private readonly List<int> _data;
            public SimpleHash(List<int> col2)
            {
                _data = col2;
            }
    
            public int GetMyHash()
            {
                _data.Sort();
                string stringHash = string.Join("", _data);
                return int.Parse(stringHash);   // warning 1: assumes you always have a convertible value
            }
        }
    
        public class MyDataSet
        {
            private readonly List<int> _dataSetValues;
    
            public MyDataSet(List<int> dataSetValues)
            {
                _dataSetValues = dataSetValues;
            }
    
            public override int GetHashCode()
            {
                SimpleHash simpleHash = new SimpleHash(_dataSetValues);
                return simpleHash.GetMyHash();   // warning 2: assumes the computed hash can fit into the int datatype given that GetHashCode() has to return int 
            }
        }
    
        public partial class Program
        {
            private static void Main(string[] args)
            {
    
                // how you split up Col1 to get your list of int's dataset is up to you
                var myDataSet1 = new MyDataSet(new List<int>(new int[] { 1,2,3 }));
                Console.WriteLine(myDataSet1.GetHashCode());
    
                var myDataSet2 = new MyDataSet(new List<int>(new int[] { 2,1,3 }));
                Console.WriteLine(myDataSet2.GetHashCode());
    
                var myDataSet3 = new MyDataSet(new List<int>(new int[] { 3,2,1 }));
                Console.WriteLine(myDataSet3.GetHashCode());
    
                Console.ReadLine();
            }
        }
    }
    

    显然这是一个微不足道的实现,但是考虑到问题的简单性,或许这已经足够了吗?

答案 1 :(得分:0)

CREATE TABLE T (Col1 INT, Col2 INT);
GO

INSERT INTO [dbo].[T]([Col1],[Col2])
VALUES (1,1), (1,2), (1,3), (2,1), (2,3), (3,3), (3,1), (3,2), (2,3),(2,1);
GO

SELECT 
    T1.Col1,
    ( 
       SELECT Convert (VARCHAR,Col2)  + ','
       FROM T T2
       WHERE T2.Col1 = T1.Col1
       ORDER BY Col2
       FOR XML PATH('') 
    ) AS Col2_Cat
INTO X
FROM T T1
GROUP BY Col1 ;


SELECT T.Col1, T.Col2,  Y.Col3
FROM T
INNER JOIN 
(
    SELECT X1.Col1, Min (X2.Col1) AS Col3  FROM X X1
    ----inner join X X2 on HASHBYTES ('SHA1',X1.Col2_Cat) = HASHBYTES('SHA1',X2.Col2_Cat)
    inner join X X2 on X1.Col2_Cat = X2.Col2_Cat
    GROUP BY X1.Col1
) AS Y
ON T.Col1 = Y.Col1;


DROP TABLE X
DROP TABLE T