如何使用SQL LIKE运算符在列中搜索精确模式?

时间:2018-11-03 12:21:13

标签: sql postgresql sql-like postgresql-9.2

我有一个如下表

    date    |                                                   tags                                                   
------------+----------------------------------------------------------------------------------------------------------
 2018-10-24 | {"table": "bank_trans", "metric": "withdrawal", "location": "UK"}
 2018-10-24 | {"table": "bank_trans", "metric": "balance", "account_id": "477", "location": "ny", "country": "USA"}
 2018-10-24 | {"table": "bank_trans", "metric": "deposit", "location": "blr", "country": "IND"}
 2018-11-02 | {"table": "bank_trans", "metric": "balance", "account_id": "477"}

如果我想要包含搜索模式的特定行,如下所示

select date, tags
from webhook_forecastmodel
where tags LIKE '%"table": "bank_trans"%' AND
      tags LIKE '%"metric": "balance"%' AND
      tags LIKE '%"account_id": "477"%';

在这种情况下,我会得到两个结果

    date    |                                                   tags                                                   
------------+----------------------------------------------------------------------------------------------------------

 2018-10-24 | {"table": "bank_trans", "metric": "balance", "account_id": "477", "location": "ny", "country": "USA"}

 2018-11-02 | {"table": "bank_trans", "metric": "balance", "account_id": "477"}

我了解SQL查询会向我返回模式匹配的行。

但是我只希望LIKE搜索模式中确切提及的行是"table": "bank_trans""metric": "balance""account_id": "477",这样我们只剩下一行。

 2018-11-02 | {"table": "bank_trans", "metric": "balance", "account_id": "477"}

有没有可能实现这一目标的方法?

2 个答案:

答案 0 :(得分:1)

您的数据结构非常糟糕。 Postgres支持JSON类型,因此您可以使用它。但是,即使使用JSON类型,您的问题也会有些挑战。

更重要的是,您似乎希望将此信息放在中,因此应将其放在此处。

鉴于您的问题中的约束,如果我假设,没有出现在键/值对内,则有一个简单的解决方案。如果是这样:

select date, tags
from webhook_forecastmodel
where tags LIKE '%"table": "bank_trans"%' AND
      tags LIKE '%"metric": "balance"%' AND
      tags LIKE '%"account_id": "477"%' AND
      tags NOT LIKE '%,%,%,%';  -- not more than three key/value pairs

答案 1 :(得分:1)

更新:此问题假设使用最新的Postgres版本。它不适用于过时且不再维护的9.2版,但我还是把它留在这里以供参考。


如注释中所述,不要使用LIKE,请使用JSON functions。为了能够做到这一点,您必须强制转换值:

select date, tags
from webhook_forecastmodel
where tags::jsonb @> '{"table": "bank_trans"}'::jsonb 
  AND tags::jsonb @> '{"metric": "balance"}'::jsonb 
  AND tags::jsonb @> '{"account_id": "477"'}::jsonb;

@>运算符检查左侧的值是否包含右侧的键/值对。


上面的方法还将返回包含比键/值对更多的行。如果您要包含完全这些键/值对的键,请使用=

select date, tags
from webhook_forecastmodel
where tags::jsonb = '{"table": "bank_trans", 
                      "metric": "balance", 
                      "account_id": "477"}'::jsonb;

jsonb数据类型对键/值对进行规范化,因此键的顺序无关紧要,并且=比较将正确进行。

在线示例:https://rextester.com/LYXHUC20162

在在线示例中,tags列中的键顺序与=运算符所用的键顺序不同,以证明JSONB规范化了JSON表示。


鉴于数据的性质,最好将列定义为jsonb以避免所有转换。