V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
MySQL 5.5 Community Server
MySQL 5.6 Community Server
Percona Configuration Wizard
XtraBackup 搭建主从复制
Great Sites on MySQL
Percona
MySQL Performance Blog
Severalnines
推荐管理工具
Sequel Pro
phpMyAdmin
推荐书目
MySQL Cookbook
MySQL 相关项目
MariaDB
Drizzle
参考文档
http://mysql-python.sourceforge.net/MySQLdb.html
LinkedIn
sunmoon1983
V2EX  ›  MySQL

求大神解答,这种 sql 应该怎么写?

  •  
  •   sunmoon1983 · 64 天前 · 1449 次点击
    这是一个创建于 64 天前的主题,其中的信息可能已经有所发展或是发生改变。

    一张表table1吧里面有 30W 数据,字段为id bigint(20),full_name varchar(66) age tinyint(3),code varchar(6) gender tinyint(1) 要展示符合下面这些条件的记录:

    如果年龄大于 1 岁,code 在( P00-P96 )这个范围内,则认为存在零概率事件-年龄与原因存在逻辑错误。 如果年龄在 15-55 岁以外,并为女性,code 在( O00-O99 )这个范围内,则认为存在零概率事件-年龄与原因存在逻辑错误 如果年龄在 15 岁以下,code 在( C11 )、C15 )、( C16 )、C18-C21 )、( C22 )、( C33-C34 )、( C67 )访问内,则认为存在零概率事件-年龄与原因存在逻辑错误 如果年龄在 5 岁以下,code 在( I05-I09 )范围内,则认为存在零概率事件-年龄与原因存在逻辑错误

    这种 sql 我应该怎么写?想了半天,只想出了一个最笨的方法 SELECT * FROM table1 WHERE (age>1 AND age<5 AND code IN('P00','P01','I05','I09')) OR (age>=5 AND age<15 AND code IN('C11','C15','C67') OR (age>=15 and age<55 AND gender=0 AN code IN('O00','O99')))

    这样,我感觉这样不行呀,求大神们给一个牛逼一点的答案吧,谢谢啦

    8 条回复    2022-07-27 17:31:52 +08:00
    eason1874
        1
    eason1874  
       64 天前
    才 30 万数据,eq OR IN 行啊,别混在一起写, 需求里每个“如果”都分开写,然后 OR 连在一起
    xy90321
        2
    xy90321  
       64 天前 via iPhone
    非要在 SQL 做是有什么难处吗 🤔
    zhemejinnameyuan
        3
    zhemejinnameyuan  
       64 天前
    可以用 case when 试试,条件自己根据情况修改下
    ```
    SELECT
    count(case when (age>1 and code in ('P00','P01','P96')) then 1 else null end) as '条件 1',
    count(case when (age<5 and code in ('I05','I06','I09')) then 1 else null end) as '条件 2'
    FROM
    table_name
    ```
    sunmoon1983
        4
    sunmoon1983  
    OP
       63 天前
    @xy90321 您给个其它的方案也行,谢谢啦
    weidaizi
        5
    weidaizi  
       63 天前
    稍微复杂一点的逻辑判断都不应该直接写到 sql 里,直接流式读出来,然后在代码里写逻辑过滤比较好
    xy90321
        6
    xy90321  
       63 天前 via iPhone
    @sunmoon1983
    能动表结构吗?能动的话就加一个零概率事件与否的标志位,每天 batch 去洗一遍。
    抽表根据标志位去抽就可以了,需要的话就加个 index ,不过才三十万,都还好吧?
    有实时性需求的话考虑加个 procedure…

    不能动表的话按照同样思路做个 view ?

    否则的话按照你的“笨办法”就可以了,能实现是第一要务。

    不在 SQL 做的话就要抽出来在程序里做了,用年龄性别做 SQL 条件先过一遍,剩下的 code 在程序里判断…
    sunmoon1983
        7
    sunmoon1983  
    OP
       62 天前
    @xy90321 因为我有分页显示的需求,我是想新建一张同样结构的表,然后再加一个标志位,然后通过程序把符合条件的数据都筛出来,再把这些数据都写到新表中,不知道这样可行否?谢谢您的回答
    asmile1993
        8
    asmile1993  
       62 天前
    -- 创建张维表,结构如下, 划分好每个 code 的年龄范围
    -- 也可以不创建,用子查询创建个临时的结果集
    create table code_age(
    code varchar(20),
    age_start varchar(20),
    age_stop varchar(20)
    )

    -- 再根据 code 和原表 table1 关联,并根据 age 来筛选
    select a.*
    from table1 a inner join
    code_age b
    where a.code = b.code
    and a.age > b.age_start
    and a.age < b.age_stop
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2906 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 45ms · UTC 14:22 · PVG 22:22 · LAX 07:22 · JFK 10:22
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.