请MSSQL高手指点一下JSON的问题

in #cn7 years ago

@jubi 小友今天与我探讨如何使用STEEMSQL查询符合条件的帖子用了哪些标签。

有关STEEMSQL的介绍以及一些我学习的记录,可以参考:

读取标签

他问的这个问题,我并不以为是个难题,所以爽快的答应了下来。

在STEEMDATA中TAGS数据已经解析好了,我们可以直接拿到,我以为STEEMSQL也是如此,结果却并不是这么回事。Comments数据表中不存在TAGS字段,仅有json_metadata字段:
json_metadata varchar 0 -1
这篇帖子为例, json_metadata数据是这个样子

在数据库中作为字符串存储。

所以要把tags数据拿出来,我们需要对这部分数据进行解析,幸运的是SQL Server 从2016版本开始,加入了JSON的支持。
详情可以参考: JSON Functions (Transact-SQL)
https://docs.microsoft.com/en-us/sql/t-sql/functions/json-functions-transact-sql

经过对上述网页以及其内相关链接的学习,我觉得我们应该用
JSON_QUERY Extracts an object or an array from a JSON string.

cur.execute("SELECT title, JSON_QUERY(json_metadata, '$.tags') as tags FROM Comments WHERE author= 'oflyhigh' and title like N'%区块链%'")


哪里不对?
我期望返回tags应该类似['literature', 'poem', 'cn'],这样的列表
结果却是: '["literature","poem","cn"]'这样的字符串!吐血!

看这个文档:
https://docs.microsoft.com/en-us/sql/t-sql/functions/json-query-transact-sql
上边介绍说的是:Extracts an object or an array from a JSON string.
底下却又说:Returns a JSON fragment of type nvarchar(max).

例子中,返回的也是列表

到底应该返回啥,我有点方。

但是问题总得要解决是吧,SQL我尝试了各种方法实在没辙,我想到的方法就是在程序这端解决,比如这样:

更进一步

这算是解答了 @jubi 小友的问题, 但是依然有以下疑问。

  • 如何用SQL直接返回tags列表, 例如:['literature', 'poem', 'cn']
  • 如果想查询包含指定tag的文章,该如何操作?比如查询包括cn tag 的文章。

因为json_metadata是字符串存储,所以对于问题二, jubi小友提出使用like '%cn%'或者正则匹配等方式,这也不失为一个好办法。或者我们还可以用JSON_QUERY(json_metadata, '$.tags') like '%cn%'缩小搜索范围,但是能否有精确匹配的查询方法呢?如果JSON_QUERY返回的是列表,我或许可以想些办法试试,但是返回的是字符串,我只好跪了。

期望各位程序大牛, SQL大牛不吝赐教,不胜感激。

参考文章

Sort:  

我是用这样分开。
...


JSON_VALUE(cm.json_metadata,'$.tags[0]') tag1,
JSON_VALUE(cm.json_metadata,'$.tags[1]') tag2,
JSON_VALUE(cm.json_metadata,'$.tags[2]') tag3,
JSON_VALUE(cm.json_metadata,'$.tags[3]') tag4,
JSON_VALUE(cm.json_metadata,'$.tags[4]') tag5
from Comments cm WITH (NOLOCK)
where ...
也是不久前上网找到的。

就好象我用于中日韩报告这样 📊🌏中日韩龙虎榜自20170811 | CJK Top Pending Payout Post since 20170811 (by @ace108)
补充...


where
    ( ( JSON_VALUE(cm.json_metadata,'$.tags[4]') in ('cn','china') ) or   
      ( JSON_VALUE(cm.json_metadata,'$.tags[3]') in ('cn','china') ) or   
      ( JSON_VALUE(cm.json_metadata,'$.tags[2]') in ('cn','china') ) or   
      ( JSON_VALUE(cm.json_metadata,'$.tags[1]') in ('cn','china') ) or   
      ( JSON_VALUE(cm.json_metadata,'$.tags[0]') in ('cn','china') ) or   

感谢分享,这个我有考虑过
对steemit而言也算是个好办法,毕竟标签数目不超过五个

你这连实现例子都给了
大大的👍

不客气。谢谢你的👍

json_metadata LIKE '%"cn"%' 把cn隔开?避免出现例如"canton"这样包含cn的单词?

感谢回复,如果能直接查就最好了
Json支持还是mongodb强大啊

@abit and @ned you guys are DESTROYING Steemit by upvoting this fucking trash and rewarding multiple $ per VIEW just because the posts are Asian.

This is fucking bullshit and you know it. You're contributing to #rewardpoolrape and I urge you to stop this bullshit immediately.

For the rest of the community, YOU SHOULD BE FLAGGING THIS SHIT, this is EXACTLY why the flags were added. Do NOT let @ned and @abit destroy what has been built here. Use your flags!!

@oflyhigh 你的SQL没有问题,可能是你的python脚本有点小问题。

如果运行以下程序,会看到和你所说一样的输出:

cur.execute("SELECT title, JSON_QUERY(json_metadata, '$.tags') as tags FROM Comments WHERE author= 'oflyhigh' and title like N'%区块链%'")
rows = cur.fetchall()
for row in rows: print(row)

其实,问题就出在哪个输出语句了,稍作改动:

for row in rows: print(row[0],row[1])

这是输出结果:

我也曾经文青过,18年前写的小诗 《花儿》,学laoyao,咱也放到区块链上 ["literature","poem","cn"]
使用PHP查询STEEM区块链 / Using PHP to query the STEEM blockchain ["cn","cn-programming","steemdev","php","steem"]
珍惜羽毛 / STEEM区块链忠实的记录你的操作 / 获得共同操作账户的真实操作者 ["cn","cn-programming","steem","steemit"]
YY 一个基于STEEM区块链的聊天工具 ["cn","cn-programming"]
STEEM区块链忠实的记录你的言行&操作 ["cn"]

谢谢答复
不过你这样只不过是把tags列表当成字符串输出了 😄,尽管看起来是列表的样子
我想要的是一个列表

你试着输出row[1][0]试试就明白了

对MSSQL这个功能不太了解。不过从数据库那里不应该直接返回object,因为object是和具体编程语言相关的。你想要得到json object也没问题,用下面的python code:

for row in rows: print(row[0],json.loads(row[1]),json.loads(row[1])[0])

Json.loads我帖子里写了😷

哈哈,没太注意。mssql的这个json功能不太清楚。也许就不支持直接返回列表吧。对我来说,能拿到json字符串就够了。

Pu ka kahah qe hana kutupu meusikrek pih...
Man kupeugah chit sang bereh..
Bereh that tulesan droe neuh hy @oflyhigh eukk, lage lam kapai are.
Nyoe kan ku tuleh nyoe koen pu laen, nyoe ku meuharap meurumpok persen bacut bak si karma, meunyoe hana jih jok persen meu bacut theh sang hana so jok keudroe kuh, jadi nyoe komen lon numpang jak siat, meuah beuh, bek neukira apam syara beh, trimong geunaseh, mnyoe awak blah deuh khen thank you very much, nyan ban :)

GREAT award winning post! Follow me @lurehound

呼吸你的灵魂,你在我的海上海滩
这颗内心的是一个圣洁的爱
我打算去死
只爱你
渴望我的灵魂我爱
我的灵魂与我交配
要死,我想和你在一起
这是我的观点
我的灵魂伴侣想要你
一个爱死亡分离
你和我是一个
爱着对方
在我悲伤的悲伤之后
人生现在是你的

아주 좋은 포스트 @oflyhigh
나를 @balcheng 따라 + 찬성 투표하십시오

虽然不懂这些技术,还是为你们感到自豪。

没啥的 😄

我只能做出崇拜状,看着你们发挥。

why so many people upvoted this post? just because of some technical advice needed??? hmmm

好像在PHP可以把这串字符转到数组再读数据是不是?我也不太懂。我前在 @justyy 的贴“ https://steemit.com/cn/@justyy/steem-api-transfer-history-ifttt-slack-how-to-use-steem-api-transfer-history-and-ifttt-to-sync-to-slack” 里看到json_decode()函数,好像可以。但如果是mssql环境下,没用过,基本不懂了。。。我等着学习吧

不懂,留名學習

不會懂,留名看你們學習

老师太谦虚了

Nice Post

用like的话, 如果数据量大的时候, 数据库应该要跪掉.. 如果要保证性能, 可能有索引最好

Thanks for this post

json_metadata LIKE'%“cn”%“把cn隔开?避免出现例如”canton“这样包含cn的单词?这是非常感兴趣的话题和巨大的收入

JSON_VALUE(cm.json_metadata,'$.tags[0]') tag1,
JSON_VALUE(cm.json_metadata,'$.tags[1]') tag2,
JSON_VALUE(cm.json_metadata,'$.tags[2]') tag3,
JSON_VALUE(cm.json_metadata,'$.tags[3]') tag4,
JSON_VALUE(cm.json_metadata,'$.tags[4]') tag5
from Comments cm WITH (NOLOCK)
where ...

mucho contenido mi hermano te felicito

A very interesting post and can be interested in my heart when I saw it greetings from my friends.

二師兄近期的文章都好高深,妹紙都已看不見車尾燈了… T_T

YOUR POST WAS IN TRENDING! UPPED and RESTEEMED

Upvoted you! Good post.

SQL 真的不是我的强項,無法幫忙 ><

谢啦

還要跟你們學習呢~

Congratulations @oflyhigh!
Your post was mentioned in the hit parade in the following category:

  • Pending payout - Ranked 5 with $ 275,89