zoukankan      html  css  js  c++  java
  • 数据库多对多关系中质数分解法的应用

    质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。
    一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数。

    100以内的质数总共有25个

    2、3、5、7、11、13、17、19、23、29、31、37、41、43、47、53、59、61、67、71、73、79、83、89、97


    了解一下质数是什么以后开始讨论我遇到的一些问题。
    1.需求介绍
    简化一下需求,需要对一系列图片进行打标签并将结果记录在数据库当中,方便根据标签查询图片。请问怎么设计这个数据库表结构。
    2.设计实现
    标签和图片之间是一个多对多的关系,那么就需要三张表,标签表(Tag),图片表(Image)和标签图片关联表(ImgTagRes)。

    CREATE TABLE `tag`  (
      `Id` int(11) NOT NULL,
      `Name` varchar(255) ,
      PRIMARY KEY (`Id`) USING BTREE
    ) 
    
    CREATE TABLE `image`  (
      `Id` int(11) NOT NULL,
      `Name` varchar(255) ,
      PRIMARY KEY (`Id`) USING BTREE
    ) 
    
    CREATE TABLE `imagetagres`  (
      `tagid` int(11) NOT NULL,
      `imgid` int(11) NOT NULL,
      PRIMARY KEY (`Id`) USING BTREE
    ) 
    
    
    #获取所有打了2标签的图片
    select imgid from imagetagres where tagid = 2
    
    #获取所有同时打了2和3标签的图片
    select imgid from imagetagres where tagid in (2,3)
    Group by imgid Having count(*) =2
    

    那么有没有别的实现方式了呢?感觉表还是太多了,能不能把关联表给删除了,只要一个图片表一个标签表?
    当然,不需要把标签Id拼接然后存放到图片表字段中的处理方式,毕竟也要保证查询时候的效率的。
    3.质数分解法
    当一个数字是由多个质数相乘而成的时候。如105=3 * 5 * 7,那么对这个数字进行质因数分解,也只会由这几个数字构成。话说回来,这个理论如何应用在这个地方呢?

    首先构建标签表的时候,++所有标签的Id都用质数替代(2、3、5、7....)。同时在图片表中,新增一个Tag字段记录给他打的所有标签的Id乘积。++

    #获取所有打了2标签的图片
    select ImgId from Image where Mod(Tag,2) = 0
    
    #获取所有同时打了2和3标签的图片
    select ImgId from Image where Mod(Tag,2*3) = 0
    

    速度真的超级快。

    质数相乘取代关联表的缺陷
    1.质数乘积是有使用限制的,当多个质数相乘的时候,很容易一不小心就爆掉int.MaxValue甚至是long.MaxValue
    2.无法快速反向获取到数字是由哪几个质因数乘积构成的。(当然可以通过加字段记录下,或者维护一个质因数序列来分解质因数)

    总结

    不是所有的多对多关系都可以使用这种方式的,这里只是提供一个思路,在一些特定场景下可以采用这种方法。继续使用上面的标签来举这个例子:
    1.标签数量是相对比较固定的,且个数不会很多。
    2.对图片打标签的时候,有个数限制,尽量不要出现对一个图片打很多标签,导致最后的乘积超出int.MaxValue的情况出现

  • 相关阅读:
    洛谷P3258 [JLOI2014]松鼠的新家
    洛谷P1306 斐波那契公约数
    bzoj4247:挂饰
    [YTU]_2354 (H 实现复数类中的加运算符重载【C++运算符重载】)
    [YTU]_2440 (C++习题 复数类--重载运算符+,-,*,/)
    [YTu]_2441 (C++习题 复数类--重载运算符2+)
    [YTu]_2439(C++习题 复数类--重载运算符+)
    10.3 重载双目运算符
    10.2.1 关于vc++不支持把类的成员函数定义为类的友元函数的处理
    10.2 运算符重载函数作为类成员函数和友元函数
  • 原文地址:https://www.cnblogs.com/cplemom/p/11761150.html
Copyright © 2011-2022 走看看