Это может быть лишь ограничением реализации директивы. Из документов :
Тип возврата поля подписки в вашей схеме должен совпадать с типом возврата соответствующего поля мутации.
blockquote>Предполагая, что есть какое-то поле
type
, которое вы используете, чтобы различатьPersonalTask
иOtherTask
, одним из обходных путей будет подписка на все задачи, но использование аргумент для сужения подписки:подписка onUpdateTask (тип: String!): Task @aws_subscribe (мутации: ["updateTask"])
Во-первых, давайте сделаем исходную таблицу такой, как эта:
Id | Value
-----+------
0001 | IN
0001 | ME
0001 | OH
0001 | ON
0002 | AC
0002 | ON
0002 | VI
0002 | ZO
0003 | ME
0003 | OO
0003 | PS
0003 | QA
Это достигается путем анализа значений, разделенных запятыми в ряды. Затем используйте мощное ключевое слово CROSS APPLY, чтобы объединиться с исходной таблицей, чтобы получить ее идентификатор. Следующий шаг - просто запросить этот CTE.
create function FnSplitToTable
(
@param nvarchar(4000)
)
returns table as
return
with
Num(Pos) as -- list of positions, numbered from 1 to 4000, largest nvarchar
(
select cast(1 as int)
union all
select cast(Pos + 1 as int) from Num where Pos < 4000
)
select substring(@Param, Pos,
charindex(',', @Param + ',', Pos) - Pos) as Value
from Num where Pos <= convert(int, len(@Param))
and substring(',' + @Param, Pos, 1) = ','
go
create proc ProcGetProductId
(
@Codes nvarchar(4000)
)
as
with
Src
(
Id,
Code
)
as
(
select '0001', 'IN,ON,ME,OH'
union all
select '0002', 'ON,VI,AC,ZO'
union all
select '0003', 'QA,PS,OO,ME'
),
Parse as
(
select
s.Id,
f.Value
from
Src as s
cross apply
FnSplitToTable(s.Code) as f
)
select distinct
p.Id
from
Parse as p
join
FnSplitToTable(@Codes) as f
on
p.Value = f.Value
option (maxrecursion 4000)
go
exec ProcGetProductId 'IN,ME' -- returns 0001 & 0003
Все остальные, похоже, очень хотят сказать вам, что вы не должны этого делать, хотя я не вижу какого-либо явного объяснения почему нет.
Помимо нарушения правил нормализации, причина в том, что вы будете выполнять сканирование таблицы по всем строкам, поскольку у вас не может быть индекса по отдельным «значениям» в этом столбце.
Проще говоря, ядро СУБД не может вести какой-либо быстрый список строк, содержащих код «AC», если вы не разбиваете его на отдельную таблицу или не помещаете в отдельный столбец.
Теперь, если у вас есть другие критерии в ваших инструкциях SELECT, которые будут ограничивать количество строк до некоторого управляемого числа, тогда, возможно, это будет хорошо, но в противном случае я бы, если вы можете,постарайтесь избежать этого решения и сделайте то, что вам уже сказали другие, разбейте его на отдельную таблицу.
Теперь, если вы застряли с этим дизайном, вы можете выполнить поиск, используя запрос следующего типа:
...
WHERE ',' + Code + ',' LIKE '%,AC,%'
Это будет:
Я не знаю, является ли последний вариант приемлемым в вашем случае Если у вас есть только двухбуквенные коды, вы можете использовать только это:
...
WHERE Code LIKE '%AC%'
Но, опять же, это будет работать ужасно, если вы не ограничите количество строк, используя другие критерии.
если у вас есть только двухбуквенные коды, вы можете использовать только это:...
WHERE Code LIKE '%AC%'
Но, опять же, это будет работать ужасно, если вы не ограничите число строк, используя другие критерии.
если у вас есть только двухбуквенные коды, вы можете использовать только это:...
WHERE Code LIKE '%AC%'
Но, опять же, это будет работать ужасно, если вы не ограничите число строк, используя другие критерии.
Вы должны хранить коды в отдельной таблице, так как у вас есть отношения многие ко многим. Если вы разделите их, то вы легко сможете проверить.
Это можно было бы сделать в том типе системы, который у вас сейчас есть, но для этого потребовался бы текстовый поиск по столбцам с несколькими поисками в каждой строке, что будет иметь огромные проблемы с производительностью по мере роста ваших данных.
Если вы попытаетесь пойти по вашему текущему пути: Вам придется разбить входную строку, потому что ничто не гарантирует, что коды в каждой записи находятся в том же порядке (или непрерывно), что и входной параметр. Затем вам нужно будет выполнить запрос
Code LIKE '%IN%'
AND Code Like '%QA%'
с дополнительным оператором для каждого кода, который вы проверяете. Очень неэффективно.
Идея UDF ниже также является хорошей идеей. Тем не менее, в зависимости от размера ваших данных и частоты запросов и обновлений, у вас также могут возникнуть проблемы.
было бы возможно создать дополнительную нормализованную таблицу, которая будет синхронизироваться по расписанию (или на основе на триггер) для вас, чтобы запросить против?
То, как вы храните данные, нарушает правила нормализации. Только одно атомное значение должно храниться в каждом поле. Вы должны хранить каждый предмет в одной строке.
Хотя все предыдущие постеры верны в отношении нормализации вашей схемы БД, вы можете делать то, что хотите, используя " UDF с табличным значением ", который принимает строку с разделителями и возвращает таблицу с одной строкой на значение в строке ... Вы можете использовать эту таблицу так же, как любую другую таблицу в вашем хранимом процессе, присоединиться к ней и т. Д ... это решит вашу непосредственную проблему ...
Вот ссылка на такой UDF: FN_Split UDF
Хотя в статье рассказывается об использовании его для передачи списка значений данных с разделителями в хранимый процесс, вы может использовать тот же UDF для работы со строкой с разделителями, хранящейся в столбце существующей таблицы ....
Это может быть невозможно, если вы застряли с этим дизайном базы данных, но было бы намного проще поставить коды в отдельных записях в другой таблице:
ProductCode
-----------
ProductID (FK to Product.ID)
Code (varchar)
Таблица может выглядеть следующим образом:
ProductID Code
-----------------
0001 IN
0001 ON
0001 ME
...
Запрос будет выглядеть примерно так (вам придется как-то передавать коды - либо в виде отдельных переменных, либо, возможно, запятой разделенная строка в процедуре):
select ProductID
from ProductCode
where Code in ('ON', 'ME')
Я согласен с другими постерами, что вы должны внимательно изучить нормализацию схемы, но я также знаю, что ярлыки являются частью жизни .
Вот пример функции, написанной на диалекте Sybase, которая делает то, что вы делаете:
ALTER FUNCTION "DBA"."f_IsInStringList"( IN @thisItem char(2), IN @thisList varchar(4000) )
RETURNS INTEGER
DETERMINISTIC
BEGIN
DECLARE is_member bit;
DECLARE LOCAL TEMPORARY TABLE tmp (thisItem char(2)) ;
DECLARE @tempstring varchar(10);
DECLARE @count integer;
IF LENGTH(TRIM(@thisList)) > 0 THEN
WHILE LENGTH(TRIM(@thisList)) > 0 LOOP
-- loop over comma-separated list and stuff members into temp table
IF LOCATE ( @thisList, ',' , 1) > 0 THEN
SET @count = LOCATE ( @thisList, ',' , 1);
SET @tempstring = SUBSTRING ( @thisList, 1,@count-1 );
INSERT INTO tmp ( thisItem ) VALUES ( @tempstring );
SET @thisList = STUFF ( @thisList, 1, @count, '' )
ELSE
INSERT INTO tmp ( thisItem ) VALUES ( @thisList );
SET @thisList = NULL;
END IF;
END LOOP ;
END IF;
IF EXISTS (SELECT * FROM tmp WHERE thisItem = @thisItem ) THEN
SET is_member = 1;
ELSE
SET is_member = 0 ;
END IF ;
RETURN is_member;
END
Затем вы можете создать простой запрос, чтобы проверить, встречается ли значение в строке, разделенной запятыми:
select * from some_table t
WHERE f_IsInStringList('OR', t.your_comma_separated_column) = 1 OR
f_IsInStringList('ME', t.your_comma_separated_column) = 1
Вопрос давности более 1 года, но все же подумал, что он будет полезен. Вы можете использовать функцию FIND_IN_SET MySql. Я не уверен, поддерживают ли это другие СУБД.
Эту функцию можно использовать следующим образом:
SELECT * FROM `table_name` WHERE FIND_IN_SET('AC', `Code`) > 0