如何用 SQL 求出「都关注了某100人」和「都收藏了某100帖子」的所有用户?

回复列表(165|隐藏机器人聊天)
  • @Ta / 2022-08-11 / /

    @无名啊,拼接

    select * from json_each('["MySQL", "PHP"]')
    

    必然需要其他编程语言,因为三个参数长这样

    select * from json_each('["MySQL", "PHP", "iphone 13"]')
    

    它比两个参数多了, "iphone 13",MySQL本身不可能凭空添加这些。

    所以,拼接
    , "iphone 13"
    和拼接
    AND uid IN (SELECT uid FROM hu60_用户拥有的手机 WHERE 手机名称 = 'iphone 13')
    有什么本质区别呢?
    并没有,后者只是比前者长了一点而已。

  • @Ta / 2022-08-11 / /

    @老虎会游泳MySQLjson_tableSQLitejson_eachjson_tree,可以应对这种『查询条件的内容和数量都必然不固定』的情况

  • @Ta / 2022-08-11 / /

    @老虎会游泳,提供参数。。也算拼接吗。。

    SQLite有个carray,可以提供多个参数,不用自己手动拼接

  • @Ta / 2022-08-11 / /

    @无名啊,这也可以应对,并且它绝对没有使用其他编程语言。你看它哪里有其他编程语言:

    SELECT uid, name FROM hu60_user WHERE
            uid IN (SELECT uid FROM hu60_bbs_topic_content WHERE content LIKE '%mysql%')
        AND uid IN (SELECT uid FROM hu60_bbs_topic_content WHERE content LIKE '%php%')
        AND uid IN (SELECT uid FROM hu60_bbs_topic_content WHERE content LIKE '%iphone%13%')
        AND uid IN (SELECT uid FROM hu60_bbs_topic_content WHERE content LIKE '%红米%k50%');
    
  • @Ta / 2022-08-11 / /

    @老虎会游泳,可是你的查询条件就限定是4个了

  • @Ta / 2022-08-11 / /

    @无名啊,提供参数当然是拼接,一个参数和两个参数之间有逗号,这个逗号怎么凭空生成?????

  • @Ta / 2022-08-11 / /

    @无名啊,可是你的查询条件也限制两个了啊!

    select * from json_each('["MySQL", "PHP"]')

    想要三个你不是需要加, "内容"吗,它从哪里来???

    既然你可以加, "内容",我为什么不能加AND uid IN (SELECT uid FROM hu60_用户拥有的手机 WHERE 手机名称 = 'iphone 13')???

  • @Ta / 2022-08-11 / /

    @老虎会游泳,从输入而来呀。。比如从前端用户传递而来

    SQL 语句就是:

    select * from json_each(?)
    
  • @Ta / 2022-08-11 / /

    @无名啊,你还没有想明白吗,两个参数是json_each(?, ?),三个参数是json_each(?, ?, ?),你既然要加, ?,我为什么不能加AND uid IN (SELECT uid FROM hu60_用户拥有的手机 WHERE 手机名称 = ?)

  • @Ta / 2022-08-11 / /

    @老虎会游泳,如果老是更改 SQL,会不会没法利用编译好的 SQL 语句缓存了

  • @Ta / 2022-08-11 / /

    @老虎会游泳,一万个参数都是

    select * from json_each(?)
    

    The json_each(X) and json_tree(X) table-valued functions walk the JSON value provided as their first argument and return one row for each element

  • @Ta / 2022-08-11 / /

    @无名啊,请看28楼,你的方案依然需要老是更改 SQL,它和我的方案没有本质区别。此外,使用预处理的情况下,SQL一共也就那么几种:

    • 一个参数的SQL
    • 两个参数的SQL
    • 三个参数
    • 四个参数
      ……
      缓存当然可以命中,毕竟参数个数也就十个以内。
      无论是你的还是我的,都一样。
  • @Ta / 2022-08-11 / /

    @老虎会游泳,不会吧,每个条件最大十个参数的话,每多一个条件,就是指数级增长了

    1个? - 1个?
    1 - 2
    ……
    1 - 10
    2 - 1
    2 - 2
    ……
    10 - 9
    10 - 10
    
  • @Ta / 2022-08-11 / /

    @无名啊,哦,json_each接受一个JSON对象。但是你还是需要其他编程语言把用户输入放进这个JSON对象啊。这和拼接SQL语句有什么本质区别呢?

    把用户输入放进JSON对象的过程,难道不使用其他编程语言?如果真的不使用,做为参数的JSON对象是怎么凭空生成的?

  • @Ta / 2022-08-11 / /

    @无名啊,存5个预编译SQL和存1024个预编译SQL对MySQL来说有什么本质区别吗?

    我可以和你打赌,用我的方案一定会比用json_each快,因为我的方案简单直接,不需要遍历JSON。

  • @Ta / 2022-08-11 / /

    @老虎会游泳,有啥表可用不,我也想看看『关系除法』能利用上多少索引

  • @Ta / 2022-08-11 / /

    @无名啊,顺便一提,SQL扩展起来很容易。比如,一种条件:

    SELECT DISTINCT	员工ID
      FROM 员工技能表 AS ES1
     WHERE NOT EXISTS (
               SELECT *
                 FROM 要求技能表
                WHERE NOT EXISTS (
                          SELECT *
                            FROM 员工技能表 AS ES2
                           WHERE ES2.员工ID = ES1.员工ID
                             AND ES2.技能 = 要求技能表.技能 ))
    

    想多个条件嘛,就加个外层呗:

    SELECT * FROM 员工信息表 WHERE 员工ID IN (
    
    SELECT DISTINCT	员工ID
      FROM 员工技能表 AS ES1
     WHERE NOT EXISTS (
               SELECT *
                 FROM 要求技能表
                WHERE NOT EXISTS (
                          SELECT *
                            FROM 员工技能表 AS ES2
                           WHERE ES2.员工ID = ES1.员工ID
                             AND ES2.技能 = 要求技能表.技能 ))
    
    ) AND 员工ID IN (
    
    SELECT DISTINCT	员工ID
      FROM 员工手机表 AS ES1
     WHERE NOT EXISTS (
               SELECT *
                 FROM 要求手机表
                WHERE NOT EXISTS (
                          SELECT *
                            FROM 员工手机表 AS ES2
                           WHERE ES2.员工ID = ES1.员工ID
                             AND ES2.手机 = 要求手机表.手机 ))
    
    )
    

    实际使用中,我肯定不选这,因为这还要我创建两个临时表(要求技能表要求手机表),还得往里面插入用户输入的数据,这妥妥的必须使用其他编程语言啊。

    这样不是好多了吗:

    SELECT * FROM 员工信息表 WHERE
            员工ID IN (SELECT 员工ID FROM 员工技能表 WHERE 技能 = '技能1')
        AND 员工ID IN (SELECT 员工ID FROM 员工技能表 WHERE 技能 = '技能2')
        AND 员工ID IN (SELECT 员工ID FROM 员工手机表 WHERE 手机 = '手机1')
        AND 员工ID IN (SELECT 员工ID FROM 员工手机表 WHERE 手机 = '手机2');
    

    有几个参数就拼接几个查询条件,多简单,多省事儿,运行起来肯定也比前者快(不需要创建临时表+能直接命中索引)。

  • @Ta / 2022-08-11 / /

    @无名啊

    有啥表可用不

    你的SQL不是已经给出了表结构嘛,

    • 员工技能表(员工ID, 技能)
    • 要求技能表(技能)

    据此创建其他表,然后填充一些随机数据用于测试呗。

  • @Ta / 2022-08-11 / /

    哦对了,我忘了说,36楼写的这个语句也需要SQL拼接,不同的子查询用AND连起来,显然不拼接做不到。

    SELECT * FROM 员工信息表 WHERE 员工ID IN (
    
    SELECT DISTINCT	员工ID
      FROM 员工技能表 AS ES1
     WHERE NOT EXISTS (
               SELECT *
                 FROM 要求技能表
                WHERE NOT EXISTS (
                          SELECT *
                            FROM 员工技能表 AS ES2
                           WHERE ES2.员工ID = ES1.员工ID
                             AND ES2.技能 = 要求技能表.技能 ))
    
    ) AND 员工ID IN (
    
    SELECT DISTINCT	员工ID
      FROM 员工手机表 AS ES1
     WHERE NOT EXISTS (
               SELECT *
                 FROM 要求手机表
                WHERE NOT EXISTS (
                          SELECT *
                            FROM 员工手机表 AS ES2
                           WHERE ES2.员工ID = ES1.员工ID
                             AND ES2.手机 = 要求手机表.手机 ))
    
    )
    
  • @Ta / 2022-08-11 / /

    @老虎会游泳,你这每一个(SELECT 员工ID FROM 员工技能表 WHERE 技能 LIKE '技能1')都是一个临时表吧(至少 SQLite 是,MySQL 没查过)

    SQL 不是针对一个表写的吗?一个表有多少个条件是固定的啊,不需要拼接条件

    (条件数量一定,条件里的值数量不定)

添加新回复
回复需要登录