2011-03-06 45 views
2

当我在我的表上有多个连接后运行select时,我有2列的输出,我想为返回的行集选择col1和col2的不同组合。在SQL中选择2列的独特组合

,我跑将smthing本查询:

select a.Col1,b.Col2 from a inner join b on b.Col4=a.Col3 

现在输出将是有点像这个

Col1 Col2 
1 z 
2 z 
2 x 
2 y 
3 x 
3 x 
3 y 
4 a 
4 b 
5 b 
5 b 
6 c 
6 c 
6 d 

现在我想的输出应该类似于如下

1 z 
2 y 
3 x 
4 a 
5 b 
6 d 

它确定,如果我随机选择第二列,因为我的查询输出像是一百万行,而我真的觉得会有一种情况,即我的Col1和Col2的输出会相同,即使这种情况下我可以编辑这个值..

你能否帮我一样..我想基本上col3需要是一个行号我猜,然后我需要选择两个cols碱基随机行号..我不知道如何transalte这到SQL

考虑的情况1a 1b 1c 1d 1e 2a 2b 2c 2d 2e现在分组将给我所有这些结果,因为我想1a和2d或1a和2b。任何这样的组合。

OK让我解释一下IM期待什么:

with rs as(
select a.Col1,b.Col2,rownumber() as rowNumber from a inner join b on b.Col4=a.Col3) 
select rs.Col1,rs.Col2 from rs where rs.rowNumber=Round(Rand() *100) 

现在我不知道我如何得到ROWNUMBER或随机正常工作!

在此先感谢。

回答

6

如果你根本不关心什么col2值返回

select a.Col1,MAX(b.Col2) AS Col2 
from a inner join b on b.Col4=a.Col3 
GROUP BY a.Col1 

如果你愿意,你可以用下面的方法随机值。

;WITH T 
    AS (SELECT a.Col1, 
       b.Col2 
       ROW_NUMBER() OVER (PARTITION BY a.Col1 ORDER BY (SELECT NEWID()) 
       ) AS RN 
     FROM a 
       INNER JOIN b 
        ON b.Col4 = a.Col3) 
SELECT Col1, 
     Col2 
FROM T 
WHERE RN = 1 

或者使用CLR聚合函数。这种方法的优点是它消除了按照partition, newid()排序的要求,下面是一个示例实现。

using System; 
using System.Data.SqlTypes; 
using System.IO; 
using System.Security.Cryptography; 
using Microsoft.SqlServer.Server; 

[Serializable] 
[SqlUserDefinedAggregate(Format.UserDefined, MaxByteSize = 8000)] 
public struct Random : IBinarySerialize 
{ 
    private MaxSoFar _maxSoFar; 

    public void Init() 
    { 
    } 

    public void Accumulate(SqlString value) 
    { 
     int rnd = GetRandom(); 
     if (!_maxSoFar.Initialised || (rnd > _maxSoFar.Rand)) 
      _maxSoFar = new MaxSoFar(value, rnd) {Rand = rnd, Value = value}; 
    } 

    public void Merge(Random group) 
    { 
     if (_maxSoFar.Rand > group._maxSoFar.Rand) 
     { 
      _maxSoFar = group._maxSoFar; 
     } 
    } 

    private static int GetRandom() 
    { 
     var buffer = new byte[4]; 

     new RNGCryptoServiceProvider().GetBytes(buffer); 
     return BitConverter.ToInt32(buffer, 0); 
    } 

    public SqlString Terminate() 
    { 
     return _maxSoFar.Value; 
    } 

    #region Nested type: MaxSoFar 

    private struct MaxSoFar 
    { 
     private SqlString _value; 

     public MaxSoFar(SqlString value, int rand) : this() 
     { 
      Value = value; 
      Rand = rand; 
      Initialised = true; 
     } 

     public SqlString Value 
     { 
      get { return _value; } 
      set 
      { 
       _value = value; 
       IsNull = value.IsNull; 
      } 
     } 

     public int Rand { get; set; } 

     public bool Initialised { get; set; } 
     public bool IsNull { get; set; } 
    } 

    #endregion 


    #region IBinarySerialize Members 

    public void Read(BinaryReader r) 
    { 
     _maxSoFar.Rand = r.ReadInt32(); 
     _maxSoFar.Initialised = r.ReadBoolean(); 
     _maxSoFar.IsNull = r.ReadBoolean(); 

     if (_maxSoFar.Initialised && !_maxSoFar.IsNull) 
      _maxSoFar.Value = r.ReadString(); 
    } 

    public void Write(BinaryWriter w) 
    { 
     w.Write(_maxSoFar.Rand); 
     w.Write(_maxSoFar.Initialised); 
     w.Write(_maxSoFar.IsNull); 

     if (!_maxSoFar.IsNull) 
      w.Write(_maxSoFar.Value.Value); 
    } 

    #endregion 
} 
+0

第二个值不是数字然后?最大不起作用! – 2011-03-06 13:17:16

+0

@Asha - 'Max'对字符串有效。它最后按字母顺序给你。你的列是什么数据类型? – 2011-03-06 13:19:19

+0

是。我知道,最大的作品,但然后1 a 1 b 1 z和2 a 2 b 2 z将返回1 z和2 z权利 – 2011-03-06 13:22:20

0

必须使用group by条款:

select a.Col1,b.Col2 
from a 
inner join b on b.Col4=a.Col3 
group by a.Col1 
+1

您不能选择col1,col2,只能按col1分组。你需要两个组 – bjorsig 2011-03-06 13:06:27

+0

这对MySQL工作得很好,尽管不知道tsql。 – krtek 2011-03-06 13:10:04

+0

MySQL是唯一允许通过简单地返回非确定性结果来指定不完整​​的group by子句的数据库。请参阅此链接以解释为什么使用它是一个糟糕的主意:http://rpbouman.blogspot.com/2007/05/debunking-group-by-myths.html – 2011-03-06 13:16:12

0

如果我理解正确的话,你想为列1和2的每个组合,可以很容易地通过使用GROUP BY或DISTINCT做一行 例如:

SELECT COL1,COL2

从您加入

GROUP BY COL1,C OL2

+0

我想要col1和col2的独特组合 – 2011-03-06 13:09:47

+0

我不想让每个distint组合有一行..考虑1a 1b 1c 1d 1e 2a 2b 2c 2d 2e现在分组将会给我所有这些结果,因为我想要1a和2d或1a和2b。任何这样的组合..第二行可以随机选择 – 2011-03-06 13:10:52

+0

如果你运行查询,你会得到col1和col2中每个组合的确切的一行,这不是愚蠢的,它是SQL 101.是不是你想要的@阿莎? – bjorsig 2011-03-06 13:12:00

3

你需要按​​仅​​得到不同的,那么因为b.Col2不包括在该组中,你需要找到一个合适的聚合函数,以减少该组中的所有值只是一个,MIN是不够好如果你只是想要其中的一个值。

select a.Col1, MIN(b.Col2) as c2 
from a 
inner join b on b.Col4=a.Col3 
group by a.Col1 
+0

第二个值是那么不是一个数字?最大不起作用! – 2011-03-06 13:17:41

+0

@Asha:[MSDN:MAX](http://msdn.microsoft.com/en-us/library/ms187751.aspx):“MAX可以与数字,字符和日期时间列一起使用,但不能与位列一起使用。不允许使用聚合函数和子查询。“ – 2011-03-06 13:20:47

+0

是。我知道,最大的作品,但然后1 a 1 b 1 z和2 a 2 b 2 z将返回1 z和2 z右 – 2011-03-06 13:22:41