假设我在 Postgres 9.4 中有下表:
items
id | name | tag_ids
1 tire -1--2-
2 wheel -1--3-
3 transmisson -3-
我想做类似的事情:
select id, tags from items where tag_ids ilike '%-1-%' or tags ilike '%-3-%';
但如果它命中两次(如 id 2),则返回命中数。这可能吗?或者可能让它作为两条记录返回,然后在应用程序代码中处理。
编辑
好的,假设我们有第二张这样的表:
items_tags
item_id tag_id
1 1
1 2
2 1
2 3
3 3
有没有办法加入它们,然后按“点击”的数量分组——我猜只是选择了行,然后按相反的顺序排列?并给出命中 tag_ids 的代表
select i.name from items inner join items_tags using (id) where items_tags.tag_id in (1,3);
但我将如何进行计数和订购。我假设有一个分组,但这超出了我的范围。
编辑 2
所以我无法让第二个查询工作。它似乎应该但不是:
select tag_ids, (tag_ids ilike '%-1-%')::int + (tag_ids ilike '%-11-%')::int as hits
from items order by hits desc;
说ERROR: column "hits" does not exist
select tag_ids, (tag_ids ilike '%-1-%')::int + (tag_ids ilike '%-11-%')::int
as hits from items where hits > 0 order by hits desc;
是的,您可以在
select
列表中使用它:或者(将布尔值转换为整数 (
TRUE -> 1, FALSE -> 0
) 然后添加:但是,如果您规范化设计并将项目标签关系存储在单独的联结表中,查询(以及许多其他查询)会容易得多。
关于“edit 2”中的错误
第一条语句是有效的(您的帖子令人困惑),错误消息仅适用于第二条语句,您在其中尝试引用子句
hits
中的输出列,WHERE
但这是不可能的。细节:解决方案:重复
WHERE
子句中的(较长的)表达式或使用子查询,或者更确切地说,拼出各个WHERE
条件:这更快,因为 Postgres 只需要验证单个匹配项来限定行,并且可以使用索引(在本例中为三字母索引)。
另外:替换
ILIKE
为 justLIKE
- 不涉及相关字符。最好的解决方案取决于缺失的信息,但数组会更优雅并且更容易索引。就像您在相关问题中遇到的那样:
已经建议的像@ypercube这样的规范化设计可能是最好的。