在PostgreSQL中,以列表作为参数选择,如果列表为空,则选择不带参数

iugsix8n  于 2024-01-07  发布在  PostgreSQL
关注(0)|答案(1)|浏览(172)

我有一个PostgreSQL数据库,其中有一个食物表和一个标签表。我需要使用psycopg3基于标签从Python GUI查询数据。如果标签参数是一个空列表,我需要使用食物表中所有餐馆的数据。
下面的查询返回所需的结果,如果一些餐厅与参数id(s)('ids_arg')有一些参数标记('tags_arg').如果'tags_arg'列表为空,那么在PostgreSQL中如何查询和计算所有没有id或标签的餐厅的数据,从而导致t.name = ANY (array[]::text[])?我可以通过添加一个UNION ALL,使用相同的查询,而不使用INNER JOIN,并根据结果使用结果表的第一行或第二行来获得所需的结果,但这大约使查询字符串文件中的行数增加了一倍。考虑到可读性,这很重要。是否有一种简洁的方法可以实现同样的效果如果没有UNION ALL或以其他方式添加大量的行,也可以进行效率分析。

SELECT Total, Total - Drinks AS "Without drinks", Drinks   
FROM (
  SELECT 
  SUM (f.prepared) 
  FILTER (
    WHERE f.date BETWEEN 'first' AND 'last'
    AND f.restaurant_id = ANY ('ids_arg')
  ) AS Total,
  SUM (f.prepared)
  FILTER (
    WHERE (f.product_id = 10 OR f.product_id = 17) 
    AND f.date BETWEEN 'first' AND 'last'
    AND f.restaurant_id = ANY ('ids_arg')
  ) AS Drinks
  FROM food f
  INNER JOIN tags t 
  ON t.restaurant_id = f.restaurant_id 
  WHERE t.name = ANY ('tags_arg'::text[])
);

字符串
编辑:这是一个dbfiddle,带有UNION ALL查询和Zeberk的答案查询。

kmb7vmvb

kmb7vmvb1#

where添加一个适当的条件:

SELECT Total, Total - Drinks AS "Without drinks", Drinks   
FROM (
  SELECT 
  SUM (f.prepared) 
  FILTER (
    WHERE f.date BETWEEN 'first' AND 'last'
    AND f.restaurant_id = ANY ('ids_arg')
  ) AS Total,
  SUM (f.prepared)
  FILTER (
    WHERE (f.product_id = 10 OR f.product_id = 17) 
    AND f.date BETWEEN 'first' AND 'last'
    AND f.restaurant_id = ANY ('ids_arg')
  ) AS Drinks
  FROM food f
  INNER JOIN tags t 
  ON t.restaurant_id = f.restaurant_id 
  WHERE array_position('tags_arg'::text[],t.name) IS NOT null 
     OR array_length('tags_arg'::text[],1) IS null
);

字符串
这也使得它是空安全的。一个常规的any(text[])产生一个null,不管你的t.name是否在tags_arg数组中,只要有一个或多个null也存在于数组中,或者t.name本身是空的,或者两者兼而有之。这是因为any()使用常规的相等=运算符,而array_position()使用is not distinct from构造。
这里有一个备忘录:demo at db<>fiddle

select tags_arg,
       tags_arg::text[] as_array,
       'tag1'=any(tags_arg::text[])                                 as "base",
       'tag1'=any(coalesce(tags_arg::text[],array['tag1']::text[])) as "+coalesce()",
       'tag1'=any(coalesce(tags_arg::text[],array['tag1']::text[]))
            OR array_length(tags_arg::text[],1) is null             as "+coalesce()+OR",
       'tag1'=any(coalesce(tags_arg::text[],array['tag1']::text[]))
            OR array_length(tags_arg::text[],1) is null
            OR array_position(tags_arg::text[],null) is not null    as "+coalesce()+OR+nullsafe",
       array_position(tags_arg::text[],'tag1') is not null 
            OR array_length(tags_arg::text[],1) is null             as "final"
from (values  ('{tag1,tag2,tag3}') --matching array
             ,('{tag4,tag5}')      --non-matching array
             ,('{tag6,null}')      --non-matching with a null
             ,('{null}')           --only a null
             ,('{}')               --empty
             ,(null)              ) as args(tags_arg);


| tags_arg|作为阵列|基地|+ codeword()|+ concoalesce()+OR| + concoalesce()+OR+nullsafe|最终|
| --|--|--|--|--|--|--|
| {tag1,tag2,tag3}|{tag1,tag2,tag3}|T我的天|T我的天|T我的天|T我的天|T我的天|
| {tag4,tag5}|{tag4,tag5}| F| F| F| F| F|
| {tag6,null}|{tag6,NULL}|* 空 || 空 *|T我的天|F|
| 联系我们|联系我们| * 空 || 空 *|T我的天|F|
| - -|- -|F| F|T我的天|T我的天|T我的天|
| * 空 || 空 *|T我的天|T我的天|T我的天|T我的天|

相关问题