简体   繁体   English

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

[英]How to search for exact pattern in a column using SQL LIKE operator?

I have a table which is like below 我有一张桌子,如下

    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"}

If I want a particular row that contains a search pattern something like below 如果我想要包含搜索模式的特定行,如下所示

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

In this case, I get back two results 在这种情况下,我得到两个结果

    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"}

I understand the SQL query returns me the rows where the pattern matches. 我了解SQL查询会向我返回模式匹配的行。

But I only want the row that is exactly mentioned in the LIKE search pattern which is "table": "bank_trans" , "metric": "balance" and "account_id": "477" which leaves us with only one row 但是我只想要在LIKE搜索模式中确切提到的行,即"table": "bank_trans""metric": "balance""account_id": "477" ,这样我们只剩下一行

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

Is there any possible way that this could be achieved? 有什么可能的方法可以实现?

You have a really bad data structure. 您的数据结构非常糟糕。 Postgres supports a JSON type, so you could use that. Postgres支持JSON类型,因此您可以使用它。 However, even with a JSON type, your question would be a bit challenging. 但是,即使使用JSON类型,您的问题也会有些挑战。

More importantly, you seem to want this information in columns so you should put it there. 更重要的是,您似乎希望将此信息放在列中,因此应该将其放在此处。

Given the constraints in your question, there is a simple solution if I assume that , does not appear inside the key/value pairs. 给定您问题中的约束,如果我假设,不会出现在键/值对中,则有一个简单的解决方案。 If so: 如果是这样的话:

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

UPDATE : this question assumes an up-to-date Postgres version. UPDATE :该问题假定使用最新的Postgres版本。 It will not work on the outdated and no longer maintained version 9.2, but I'm leaving it here anyway for reference. 它不适用于过时且不再维护的9.2版,但无论如何我还是把它留在这里作为参考。


As mentioned in the comments don't use LIKE, use JSON functions . 如注释中所述,不要使用LIKE,请使用JSON函数 In order to be able to do that, you have to cast the value: 为了能够做到这一点,您必须强制转换值:

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;

The @> operator checks if the value on the left side contains the key/value pair on the right side. @>运算符检查左侧的值是否包含右侧的键/值对。


The above would also return rows that contain more than those key/value pairs. 上面的代码还将返回包含比这些键/值对更多的行。 If you want those that contain exactly those key/value pairs, use = 如果您想要包含正好包含这些键/值对的键,请使用=

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

The jsonb data type normalizes the key/value pairs, so the order of the keys is irrelevant and the = comparison will work correctly. jsonb数据类型规范了键/值对,因此键的顺序无关紧要,并且=比较将正确进行。

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

In the online example I have a different order of keys in the tags column compared to those used for the = operator to demonstrate that JSONB normalizes the JSON representation. 在在线示例中,与用于=运算符的键相比,我在tags列中的键顺序不同,以证明JSONB规范化了JSON表示形式。


Given the nature of your data, it's probably better to define the column as jsonb to avoid all the casting. 考虑到数据的性质,最好将列定义为jsonb以避免所有转换。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM