Итак, я думал о создании динамического SQL-вопроса, что означает, что я хочу, чтобы количество параметров было динамическим.
Посмотрев на это: Параметризация предложения SQL IN, я подумал, что использование типа "% x%" МЕДЛЕННО и нехорошо.
На самом деле я хотел бы использовать ключевое слово IN и иметь его примерно так:
выберите UserId из NameTable, где Name IN (@List_of_names)
Где @List_of_names может содержать т.е.
(меня зовут Йохан, поэтому он там))
Так что все это должно совпадать с Йоханом Филипом Экбергом.
Я хочу использовать либо LINQ to SQL, либо LINQ to SQL (хранимая процедура) с использованием C#.
Предложения и мысли, пожалуйста!
----------------- Очистка сценария и таблиц -------------------------
Представьте, что у меня есть следующее: таблица с пользователями, таблица с именами и таблица, которая связывает имена с определенным пользователем.
Итак, имея
[User Table]
User ID Full Name
1 Johan Filip Ekberg
2 Anders Ekberg
[Names]
Name ID Name
1 Filip
2 Ekberg
3 Johan
4 Anders
[Connect Names]
Name ID User ID
1 1
2 1
3 1
2 4
2 2
Итак, если я хочу искать: Экберг
Возврат должен быть:
Если я хочу найти Йохана Экберга
Если я хочу найти Андерса
Количество «поисковых имен» может быть бесконечным, если у меня есть имя: Йохан Андерс Карл Филип Экберг (это всего лишь 1 человек с множеством имен), и я просто пропускаю «Карл Филип», я хочу найти этого пользователя.
Это все проясняет?





Я слышал, что в SQL Server 2008 есть функция, называемая параметрами таблицы, поэтому вы можете передать таблицу в качестве параметра функции или хранимой процедуры.
А пока вы можете использовать классику:
SELECT UserId FROM NameTable WHERE CHARINDEX( '|' + Name + '|', '|Filip Ekberg|Filip|Ekberg Filip|') > 0
Это означает, что имя столбца может быть любым из значений, которые есть в списке.
Вы также можете передать параметр XML в хранимую процедуру, а затем использовать его в качестве таблицы в своем коде с помощью команды OPENXML.
Я еще не тестировал это, но я читал, что это будет новая функция SQL Server 2008!
Думаю, мне было непонятно, как устроены таблицы! Я немного перефразирую вопрос.
Вы говорите, что хотите использовать IN? IN ищет точные совпадения, поэтому, если вы используете IN ('Ekberg')
Вы найдете только Экберг, а не Андерса Экберга.
Если вы хотите, чтобы указанное выше помогло найти Андерса Экберга, вам нужен лайк '% Ekberg'
Фактически, в вашем втором примере, где у вас есть имя A B C и вы передаете A C, вы хотите, чтобы он нашел A B C.
На самом деле вы хотите получать лайки за каждое произнесенное вами слово. Есть и другие способы добиться того, что вам кажется. Не возражаете, если я спрошу в первую очередь базу данных, с которой вы работаете? :) Спасибо
Это SQL Server, и IN выберет Андерса Экберга. Потому что Select выберет все идентификаторы, у которых Экберг и Андерс и Филип используют этот NameID.
Извините, что? Если вы используете select UserId из NameTable, где Name IN (@List_of_names), который является вашим запросом, а ваш список имен ('Anders', 'Ekberg'), например, вы никогда не найдете 'Anders Ekberg' Только точные совпадения
Первый пример был немного плохим, поэтому я добавил еще один. Если вы выберете из таблицы Name и присоединитесь к Name Connections, где Name IN ('Ekberg'), вы получите строки как для Андерса, так и для Филипа. я это проверил. Но проблема в том, что я не могу сделать динамическое количество параметров.
Хорошо, я думаю, что у меня возникает путаница, потому что ваш выбранный указанный идентификатор пользователя, и я искал идентификатор пользователя столбца в вашем описании, и он находится в первой таблице с полными именами рядом с ним. на самом деле вам нужны идентификаторы пользователя из таблицы сопоставления, где идентификатор имени присоединяется к таблице имен, а имя находится в списке
Точно. Вот тут и начинается проблема :)
Что вы действительно хотите, так это передать массив в процесс SQL Server и использовать этот массив в списке IN по вашему выбору, вам может понравиться этот support.microsoft.com/kb/555266, он показывает, как передавать массивы в процесс. Я знаю, что для этого есть nn встроенная поддержка. Обычно мы передаем XML процессу и зацикливаем его.
GL с ним, метод работает, мы его использовали, извиняюсь за первоначальную путаницу :)
Здорово! Я собираюсь взглянуть на это!
Похоже, что SQL 2008 - это вариант, поэтому лучше всего передать параметр таблицы. Еще одно возможное решение для тех, кто еще не может перейти на 2008 год, - это написать возвращающую табличное значение UDF, которая генерирует таблицу из строки с разделителями. Тогда вы можете сделать что-то вроде этого:
SELECT DISTINCT
CN.user_id
FROM
dbo.Names N
INNER JOIN dbo.Connect_Names CN ON CN.name_id = N.name_id
INNER JOIN dbo.GetTableFromNameList(@names) T ON T.name = N.name
Это даст вам идентификаторы пользователей, в которых ЛЮБОЕ из переданных имён совпадает с ЛЮБОЙ из имен пользователей. Если вы хотите изменить его так, чтобы он давал совпадение только тогда, когда ВСЕ переданные имена совпадают с одним из имен пользователя, вы можете сделать что-то вроде этого:
SELECT
CN.user_id
FROM
dbo.Names N
INNER JOIN dbo.Connect_Names CN ON CN.name_id = N.name_id
INNER JOIN dbo.GetTableFromNameList(@names) T ON T.name = N.name
GROUP BY CN.user_id
HAVING COUNT(*) = (SELECT COUNT(*) FROM dbo.GetTableFromNameList(@names))
Я не тестировал этот второй запрос, поэтому вам, возможно, придется с ним повозиться. Кроме того, вы можете создать локальную таблицу и заполнить ее функцией, чтобы вам не приходилось запускать функцию несколько раз.
Я могу опубликовать свою версию строки в табличную функцию, если она вам понадобится. Кроме того, если вы хотите использовать LIKE, а не точные совпадения, вы можете это сделать.
Из аналогичного вопроса только для SQL здесь: SQL-запрос: имитация операции «И» для нескольких строк вместо подзапроса
Попробуй это.
List<string> targets = new List<string>() {"Johan", "Ekberg"};
int targetCount = targets.Count;
//
List<Users> result =
dc.Names
.Where(n => targets.Contains(n.Name))
.SelectMany(n =>
dc.ConnectNames.Where(cn => cn.NameId == n.NameId)
)
.GroupBy(cn => cn.UserId)
.Where(g => g.Count() == targetCount)
.SelectMany(g =>
dc.Users.Where(u => u.UserId == g.Key)
)
.ToList();
Это код от руки, поэтому, вероятно, там есть какие-то синтаксические ошибки.
Итак, вы бы сказали, что использование параметров таблицы и создание настраиваемой таблицы данных с количеством имен от 1 до N и использование этого в хранимой процедуре было бы хорошо? Я попробую это!