Ответ 1
Если вам просто все равно, что возвращается 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
}