Database 板


LINE

我从来没接触过10万笔以上资料的案例 所以我本来是想 240万 join 1600万 的资料 你应该是会用MOONY135的分批跑排程之类的做法? 不过若是10万笔以下的资料要跑的话应该还是能一句sql跑完所以来解一下题目 我重新排版一下 先以实际执行确定这个写法在我这边是可以跑的 https://i.imgur.com/uX3BOfs.png ※ 引述《Wengboyu ( )》之铭言: : SAS sql的code还是有些不同,我做了一些改写碰到了一些小问题 所以你的写法我没有SAS资料库的环境来验证跑起来哪边有问题 : 我要计算table a每一笔,a.doctor在a.date过去一年内收过多少病人(不重复) 这边因为时间并不是问题,所以简化一下先把时间去掉 查询目标改为「每个医生不限时间收过多少不重复病人」 先来个测试用资料 医生的表格是 dr (doctor),有三个医生,a b c SELECT * FROM dr; +----+-----+ | dr | sid | +----+-----+ | a | A | | b | Z | | c | Z | +----+-----+ 3 rows in set (0.000 sec) 病人没有表格,有三个病人,x y z 看病的表格是 sv (service),有五笔纪录,c医生没有任何看病纪录 SELECT * FROM sv; +----+-----+----+ | sv | sid | dr | +----+-----+----+ | 1 | x | a | | 2 | x | b | | 3 | y | b | | 4 | z | b | | 5 | x | b | +----+-----+----+ 5 rows in set (0.000 sec) SELECT dr.*,sv.sid FROM dr LEFT JOIN sv ON dr.dr=sv.dr; +----+-----+------+ | dr | sid | sid | +----+-----+------+ | a | A | x | | b | Z | x | | b | Z | y | | b | Z | z | | b | Z | x | | c | Z | NULL | +----+-----+------+ 6 rows in set (0.000 sec) 医生表格的 sid 不知道有何作用,但是原本的例子看起来是要捞出来的,所以留着 看病表格的 sid 是病人,捞出来是为了滤掉重复用的 於是这边的问题就是有两个栏位都是 sid 如果对这个 join 表格再度查询一次,则 SELECT * FROM ( SELECT dr.*,sv.sid FROM dr LEFT JOIN sv ON dr.dr=sv.dr )tb; ERROR : Duplicate column name 'sid' 在 mariaDB 中就直接错误了 错误发生後续就不会继续跑 所以第一次join出来的表格,把看病的sid重新命名为s SELECT * FROM ( SELECT dr.*,sv.sid s FROM dr LEFT JOIN sv ON dr.dr=sv.dr )tb; +----+-----+------+ | dr | sid | s | +----+-----+------+ | a | A | x | | b | Z | x | | b | Z | y | | b | Z | z | | b | Z | x | | c | Z | NULL | +----+-----+------+ 6 rows in set (0.001 sec) b医生重复看了病人 x ,重复的过滤掉 SELECT * FROM ( SELECT DISTINCT dr.*,sv.sid s FROM dr LEFT JOIN sv ON dr.dr=sv.dr )tb; +----+-----+------+ | dr | sid | s | +----+-----+------+ | a | A | x | | b | Z | x | | b | Z | y | | b | Z | z | | c | Z | NULL | +----+-----+------+ 5 rows in set (0.000 sec) 这个表格把数量统计起来就是目标:「每个医生不限时间收过多少不重复病人」 SELECT dr,sid,count(*),count(1),count(s) FROM ( SELECT DISTINCT dr.*,sv.sid s FROM dr LEFT JOIN sv ON dr.dr=sv.dr )tb GROUP BY dr,sid; +----+-----+----------+----------+----------+ | dr | sid | count(*) | count(1) | count(s) | +----+-----+----------+----------+----------+ | a | A | 1 | 1 | 1 | | b | Z | 3 | 3 | 3 | | c | Z | 1 | 1 | 0 | +----+-----+----------+----------+----------+ 3 rows in set (0.001 sec) count(1) 和 count(*) 的结果是一样的,听说差别只在效率 count(s) 则是会计算s栏位中非null的数量 因为 c医生的看病数为 0 ,所以把NULL算成一笔是错误的,这边要用 count(s) 如果看病数为0的医生完全不打算显示的话,那一开始第一次的join就不要用 LEFT JOIN SELECT dr.*,sv.sid SELECT dr.*,sv.sid FROM dr LEFT JOIN sv FROM dr JOIN sv ON dr.dr=sv.dr; ON dr.dr=sv.dr; +----+-----+------+ +----+-----+-----+ | dr | sid | sid | | dr | sid | sid | +----+-----+------+ +----+-----+-----+ | a | A | x | | a | A | x | | b | Z | x | | b | Z | x | | b | Z | y | | b | Z | y | | b | Z | z | | b | Z | z | | b | Z | x | | b | Z | x | | c | Z | NULL | +----+-----+-----+ +----+-----+------+ 5 rows in set (0.000 sec) 6 rows in set (0.000 sec) 如果保证没有null,这样最後用 count(1),count(*),count(s),count(dr) 都可以 回到目标:「每个医生不限时间收过多少不重复病人」 SELECT dr,sid,count(s) dr_sv_volumn FROM ( SELECT DISTINCT dr.*,sv.sid s FROM dr LEFT JOIN sv ON dr.dr=sv.dr )tb GROUP BY dr,sid; +----+-----+--------------+ | dr | sid | dr_sv_volumn | +----+-----+--------------+ | a | A | 1 | | b | Z | 3 | | c | Z | 0 | +----+-----+--------------+ 3 rows in set (0.001 sec) 以上是简化过的目标:不限时间 如果要限定一年之内,就把时间的条件加进去 SELECT date,sid,doctor,count(s) doctor_service_volumn FROM ( SELECT DISTINCT a.date,a.sid,a.doctor,b.sid s FROM a LEFT JOIN b ON a.doctor=b.doctor AND a.date BETWEEN b.date AND DATE_ADD(b.date,INTERVAL 1 YEAR) )tb GROUP BY date,sid,doctor; Proc sql; create table want as select *, count(*) as doctor_service_volume from (select distinct a.*, b.SID from a left join b on a.DoctorID = b.DoctorID && a.date >= b.date && b.date >= intnx('year', a.date, -1, 'same') ) group by date, SID, DoctorID; quit; 比较一下可以看到两个地方是不一样的 SELECT date,sid,doctor,count(s) doctor_service_volumn FROM ( SELECT DISTINCT a.date,a.sid,a.doctor,b.sid s FROM a LEFT JOIN b ON a.doctor=b.doctor AND a.date BETWEEN b.date AND DATE_ADD(b.date,INTERVAL 1 YEAR) )tb GROUP BY date,sid,doctor; 其中一个比较让我意外的是里面join出来的表格居然外面的可以select 前面我说过会有这个错误:ERROR : Duplicate column name 'sid' 在 mariaDB 中就直接错误,我觉得是合理的 不然 select sid 到底是要捞哪个 sid ? 而你的 SAS sql 没报错,继续跑出结果,我猜是不是不同资料库对语法的行为不同? 莫非是因为你是 select * 而不是 select sid, 所以 SAS sql 就把两个 sid 都捞出来不报错? 如果是这样的话,那之後还有 GROUP BY date,sid,doctor 这个 group by sid 的又是哪个 sid ? -- ▁ ◢ ▄▄▄▄▄▄▄ . * ▁▁ 狼出没注意! . ˊ . ▅▂ ▂▅ ◢◤ ▄▄▄▄▄▄▄ . ▃▂▁ http://chippclass.99k.org/↙◆ ▇▇ telnet://bs2.to (P_chippclass)↙◆ ▆▅▂ ψchippclass ▅▂▁ --



※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 114.136.222.203 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/Database/M.1602779386.A.CD4.html







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:iOS站内搜寻

TOP