Отказ от ответственности: не мой код, не мой дизайн базы данных!
У меня есть столбец censusblocks(varbinary(max), null)
в таблице базы данных MS SQL Server 2008 (для простоты назовите его foo
).
Этот столбец на самом деле является null
или длинным списком от 1 до n из int
. int
s на самом деле являются внешними ключами другой таблицы (назовите ее censusblock
с pk id
типа int
), нумерацией от 1 до ~ 9600000.
Я хочу запросить , чтобы извлечь список censusblocks
из foo
, и использовать извлеченный список int
из каждой строки, чтобы найти соответствующую строку censusblock
. Есть длинный скучный остаток запроса, который будет использоваться оттуда, но начинать его нужно с блоков переписи, извлеченных из столбца foo
таблицы censusblocks
.
Это преобразование и поиск в настоящее время обрабатываются на среднем уровне, с небольшим служебным классом .NET для преобразования из List<int>
в byte[]
(и наоборот), который затем записывается в / считывается из дБ как varbinary
. Я хотел бы сделать то же самое, чисто в SQL.
Требуемый запрос будет выглядеть примерно так:
SELECT f.id, c.id
FROM foo f
LEFT OUTER JOIN censusblock c ON
c.id IN f.censusblocks --this is where the magic happens
where f.id in (1,2)
Что приведет к:
f.id | c.id
1 8437314
1 8438819
1 8439744
1 8441795
1 8442741
1 8444984
1 8445568
1 8445641
1 8447953
2 5860657
2 5866881
2 5866881
2 5866858
2 5862557
2 5870475
2 5868983
2 5865207
2 5863465
2 5867301
2 5864057
2 5862256
Примечание: 7-значные результаты совпадают. Диапазон, как указано выше, 1-7 цифр.
Фактический столбец censusblocks
выглядит как
SELECT TOP 2 censusblocks FROM foo
, что приводит к
censublocks
0x80BE4280C42380C7C080CFC380D37580DC3880DE8080DEC980E7D1
0x596D3159858159856A59749D59938B598DB7597EF7597829598725597A79597370
Для дальнейшего пояснения, вот основные методы преобразования классов .NET:
public static List<int> getIntegersFromBytes(byte[] data)
{
List<int> values = new List<int>();
if (data != null && data.Length > 2)
{
long ids = data.Length / 3;
byte[] oneId = new byte[4];
oneId[0] = 0;
for (long i = 0; i < ids; i++)
{
oneId[0] = 0;
Array.Copy(data, i * 3, oneId, 1, 3);
if (BitConverter.IsLittleEndian)
{ Array.Reverse(oneId); }
values.Add(BitConverter.ToInt32(oneId, 0));
}}
return values;
}
public static byte[] getBytesFromIntegers(List<int> values)
{
byte[] data = null;
if (values != null && values.Count > 0)
{
data = new byte[values.Count * 3];
int count = 0;
byte[] idBytes = null;
foreach (int id in values)
{
idBytes = BitConverter.GetBytes(id);
if (BitConverter.IsLittleEndian)
{ Array.Reverse(idBytes); }
Array.Copy(idBytes, 1, data, count * 3, 3);
count++;
} }
return data;
}