PostgreSQL-所有(数组)运算符-建议
示例代码如下:所有或任何操作员未工作。我需要比较数组的所有值PostgreSQL-所有(数组)运算符-建议,postgresql,plpgsql,Postgresql,Plpgsql,示例代码如下:所有或任何操作员未工作。我需要比较数组的所有值 CREATE OR REPLACE FUNCTION public.sample_function( tt_sample_function text) RETURNS TABLE (..... ) LANGUAGE 'plpgsql' COST 100 VOLATILE ROWS 1000 AS $BODY$ declare e record; v_cnt IN
CREATE OR REPLACE FUNCTION public.sample_function(
tt_sample_function text)
RETURNS TABLE (..... )
LANGUAGE 'plpgsql'
COST 100
VOLATILE
ROWS 1000
AS $BODY$
declare
e record;
v_cnt INTEGER:=0;
rec record;
str text;
a_v text [];
BEGIN
FOR rec IN ( SELECT * FROM json_populate_recordset(null::sample_function ,sample_function::json) )
LOOP
a_v:= array_append(a_v, ''''||rec.key || '#~#' || rec.value||'''');
END LOOP;
SELECT MAInfo.userid FROM
(SELECT DISTINCT i.userid,
CASE WHEN (i.settingKey || '#~#' || i.settingvalue) = ALL (a_v)
THEN i.settingKey || '#~#' || 'Y'
ELSE i.settingKey || '#~#' || 'N' END
AS MatchResult
FROM public.sample_table i
WHERE (i.settingKey || '#~#' || i.settingvalue) = ALL (a_v)
GROUP BY i.userid, MatchResult) AS MAInfo
GROUP BY MAInfo.userid
HAVING COUNT(MAInfo.userid) >= 1;
RETURN QUERY (....);
END;
$BODY$;
输入为
SELECT public.sample_function(
'[{"key":"devicetype", "value":"TestType"},{"key":"ostype", "value":"TestType"}]'
)
任何建议,为什么我的ALL操作员不工作。我的意思是它总是给假,它应该匹配所有的数组元素
注:数据当然在表中。您将事情复杂化了。您不需要FOR循环或数组来进行比较。您可以在一个语句中完成这一切。不需要额外的类型或生成数组 函数的参数应该声明为
jsonb
,因为您显然希望在那里传递有效的JSON
我不明白你想用CASE表达式实现什么。WHERE子句只返回与本例中第一个条件匹配的行,因此永远不会到达第二个条件
我也不明白为什么会有这样的情况,因为您完全放弃了外部查询中的结果
但是尽可能保持原始结构,我认为您可以将其简化为一个CREATETABLE as语句,并摆脱所有数组处理
CREATE OR REPLACE FUNCTION public.sample_function(p_settings jsonb)
RETURNS TABLE (..... )
LANGUAGE plpgsql
AS $BODY$
declare
...
begin
CREATE TEMP TABLE hold_userID AS
SELECT MAInfo.userid
FROM (
-- the distinct is useless as the GROUP BY already does that
SELECT i.userid,
CASE
-- this checks if the parameter contains the settings key/value from sample_table
-- but the WHERE clause already makes sure of that???
WHEN p_settings @> jsonb_build_object('key', i.settingKey, 'value', i.settingvalue)
THEN i.settingKey || '#~#' || 'Y'
ELSE i.settingKey || '#~#' || 'N'
END AS MatchResult
FROM public.sample_table i
WHERE (i.settingKey, i.settingvalue) = IN (select t.element ->> 'key' as key,
t.element ->> 'value' as value
from jsonb_array_elements(p_settings) as t(element))
GROUP BY i.userid, MatchResult
) AS MAInfo
GROUP BY MAInfo.userid
HAVING COUNT(MAInfo.userid) >= 1;
return query ...;
end;
$body$
如果要检查某些用户是否具有传递给函数的所有设置,则实际上不需要大小写表达式,只需要具有适当的
条件
所以也许你想要这个:
CREATE TEMP TABLE hold_userID AS
SELECT i.userid,
FROM public.sample_table i
WHERE (i.settingKey, i.settingvalue) = IN (select t.element ->> 'key' as key,
t.element ->> 'value' as value
from jsonb_array_elements(p_settings) as t(element))
GROUP BY i.userid
HAVING COUNT(*) = jsonb_array_length(p_settings);
或者:
SELECT i.userid
FROM (
select userid, settingkey as key, settingvalue as value
from public.sample_table
) i
group by i.userid
HAVING jsonb_object_agg(key, value) = p_settings
我不明白你用的是什么样的表达方式。WHERE
子句已经使用了=ALL(…)
,因此将永远无法到达CASE表达式的ELSE部分。好的,谢谢,但是-1。使事情复杂化,因为这是一个部分,需求非常复杂,无法通过此实现。请忽略sql查询。2.在这里,我将不起作用,因为我必须匹配输入中的每个值(键和值),这就是为什么我试图与所有值进行比较。3.这里所有的操作员都在按照我的预期工作。有了IN运算符,我可以用一个简单的表结构来实现,在这里没有帮助。非常感谢!我把上述想法融入到我所有复杂的永无止境的解决方案中。它工作得很好,解决了我的一部分问题。再次感谢。“因为我必须匹配每个值”-这正是上次使用count(*)=jsonb\u array\u length()
的查询所做的。CASE表达式无法实现这一点。我还添加了另一种检查“所有”设置的方法
SELECT i.userid
FROM (
select userid, settingkey as key, settingvalue as value
from public.sample_table
) i
group by i.userid
HAVING jsonb_object_agg(key, value) = p_settings