我有一个如下表
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"}
有没有可能实现这一目标的方法?
答案 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
以避免所有转换。