「更新」油猴脚本---freebuf文章图片去除!small并自动缩放图片大小到100% 技术文章
我之前写过一篇文章是关于freebuf文章图片去除!small得,地址在这里:https://mrxn.net/jswz/modify_freebuf_pic.html,但是后来我发现有一个BUG,很严重得那种:因为我当时在写插件的时候是在文章全部浏览完后直接写得,这也就导致了我当时忽略了 freebuf 的图片是懒加载的,这样的话如果还是像我之前那样直接去除图片 src 末尾的 !small ,会导致没有在第一屏内的图片不会被渲染出来!so ,趁着这次五一国际劳动节放假当天,我就来更新来了!本次更新重新设计了一下,就是取消掉了那个小标签添加,在文章页面禁用了lazyload加载,当你读文章慢慢往下滚动的时候就可以自动去除图片末尾的 !small 了,而且回自动修改图片的宽度属性到 100% (受父节点限制,不会撑爆的),尽可能的显示图片大小从而方便阅读。
Greasy Fork 在线下载安装
0day.today「一个0day漏洞交易市场」 资源分享
在pastebin上看到的,想要买卖0day的可以进去看看,不想做买卖的也可以进去瞧瞧,原文如下:
be careful: if http://0day.today redirecting to pastebin page - your ip block. Download TOR Browser and use TOR mirror http://mvfjfugdwgc5uwho.onion
意思就是说如果你直接浏览器打开 http://0day.today 跳转回 pastebin.com 说明你的IP被封了,换TOR浏览器打开他们在暗网上的网站地址:http://mvfjfugdwgc5uwho.onion .
打开界面如上图所示,你可以选择你的语言,包括:英语、俄语、德语、捷克语(土耳其)、法语、意大利语、希腊语、西班牙语、罗马尼亚文、波兰语、阿拉伯语(沙拉阿拉伯)、日文、中文等语种可供选择,但是建议不选择,默认英文即可。至于为什么不建议选择,当然是为了那可怜的隐私。
要进入网站需要同意网站的声明:网站收集的EXP和各种漏洞仅作为安全研究人员用途,我们只是收集并不负责,你需要自行承担所有的责任。(锅摔干净了!)
下面的用户协议、法律信息、声明等等就不一一翻译了,我想大部分人从不看网站的这些协议吧,简单的粘贴一下Google机翻的:
用户协议 任何访问该网站0day.today的人必须接受条款和条件(如下所列),或者立即离开0day.today。 如果您不同意0day.today的规则,您必须立即离开0day.today。 0day.today团队很高兴邀请您参与我们的项目 - 您需要做的就是注册开始! 一般信息 关于0day.today及其团队的官方信息仅在0day.today网站上发布。 不要依赖别人说的负面批评/谣言 - 这是一个误区!我们不会破坏任何网站,也不会攻击任何网络服务器。 0day.today团队专门研究bug研究,而不是恶意行为。 0day.today在没有任何保证的情况下发布,仅用于教育目的。 0day.today及其团队不负责非法使用所提供的信息。 0day.today是您的新数字朋友,他将帮助您避免网站上的许多安全问题! 司法,法律,程序员和源代码 我们特别注意遵守所有必要的欧洲法律,但我们行使权利以安全的方式交换信息。 所有提交的漏洞都将转发给产品制造商,并将发布以保护您的本地环境。 如果提交包含恶意代码,非法注释和/或敏感详细信息,则将删除或修改提交。 0day.today 1337day使命宣言 0day.today 1337day Mission将提供标准和技术数据库,以保护您的信息系统免受可能的威胁。 某些威胁可能针对您的信息/流程的机密性或完整性以及您的信息和服务的可用性。 在0day.today 1337day,我们会在发现新的安全漏洞时尽快通知您,以便您采取适当的措施来修补/修复它们。 0day.today 1337day团队的正式声明 我们不批准或鼓励任何人取消任何供应商许可,破坏网站,侵入数据库和/或使用欺诈或被盗材料进行交易。 我们不公布反对某些宗教,支持恐怖主义/种族主义或任何负面性质的咨询/漏洞。 我们不允许会员在我们的数据库或电子邮件中进行任何犯罪活动或请求。此类示例将立即删除,不做任何评论。 0day.today 1337day按“原样”向您提供信息,对您造成的任何损害不承担任何责任。 Inj3ct0r包含在某些国家/地区可能被视为非法的信息。 此类信息仅供教育之用,不得用于非法活动。 // 0day.today 1337day行政
当你同意这些协议后,点击 Yes, I agree 就进入网站了。进入网站后可以注册搜索等等,网站支持BT币作为交易货币,网站同时提供收费的和免费的漏洞,漏洞EXP类型包括(local, remote, DoS, PoC, 等) ,目前漏洞库共收录32442个漏洞,包括0day,各种语言的,平台,比如Java、php(包括国内的74CMS,国外wordpress等)、Android、Windows、Linux软件还包括像Sony电视等硬件的漏洞,你也可以通过搜索来搜索你感兴趣的漏洞或者是根据分类来筛选。而且漏洞都比较新,下面列举首页的一部分漏洞:
Twitter reset account Private Method 0day Exploit, Instagram bypass Access Account Private Method Exploit、 SMF 2.1 Beta 2 Remote Code Execution 0day Exploit、 SMF 2.0.x Remote Code Execution 0day Exploit、 Snapchat takeover any account 0day Exploit、 Tebilisim Remote File Read Vulnerability、 Mod_Security <= 3.0 Bypass XSS Payload Vulnerability、 facebook - Grabbing permanent access token which Never expires of your accounts and pages .、 Google Chrome 72.0.3626.121 / 74.0.3725.0 - NewFixedDoubleArray Integer Overflow Exploit、 Atlassian Confluence Widget Connector Macro Velocity Template Injection Exploit、 ManageEngine Applications Manager 11.0 < 14.0 - SQL Injection / Remote Code Execution Exploit、 MailCarrier 2.51 - POP3 (RETR) SEH Buffer Overflow Exploit、 Lavavo CD Ripper 4.20 Local SEH Exploit、 VirtualBox 6.0.4 r128413 - COM RPC Interface Code Injection Host Privilege Escalation Exploit、 RARLAB WinRAR ACE Format Input Validation Remote Code Execution Exploit、Sony Smart TV Information Disclosure / File Read Vulnerabilities、 Ross Video DashBoard 8.5.1 - Insecure Permissions Vulnerability、 LibreOffice 6.0.7 / 6.1.3 - Macro Code Execution Exploit、 Apache Pluto 3.0.0 / 3.0.1 - Persistent Cross-Site Scripting Vulnerability、 osTicket 1.11 - Cross-Site Scripting / Local File Inclusion VulnerabilitiesUliCMS 2019.2 / 2019.1 - Multiple Cross-Site Scripting Exploit、 74CMS 5.0.1 - Cross-Site Request Forgery (Add New Admin User) Exploit、 WordPress Contact Form Builder 1.0.67 Plugin - CSRF / Local File Inclusion Exploit、 Backup Key Recovery 2.2.4 - Denial of Service Exploit、 HeidiSQL 10.1.0.5464 - Denial of Service Exploit、 Linux - (page->_refcount) Overflow via FUSE Exploit、 Linux/x86 - Rabbit Shellcode Crypter (200 bytes)、 Linux/x86 - Cat File Encode to base64 and post via curl to Webserver Shellcode (125 bytes)、 Linux/x86 - add user to passwd file Shellcode (149 bytes)、 Linux/x86 - XOR Encoder / Decoder execve(/bin/sh) Shellcode (45 bytes)
B站源码泄露后续-GO代码行数、网警锁定、关键词过滤、人气倍率、真假播放量、作弊粉丝数 业界新闻
B站(bilibili)后端源码泄露,我们可以从中了解多少信息安全知识和代码里的有趣信息 业界新闻
B站源码泄露背景:
晚间逛V2社区的时候刷到了这么一条帖子:Openbilibili? B 站在 Github 上公开了自己的后端源代码。
下面各位V友吃瓜群众或喜闻乐见,或惊奇不已,我是个凡人我也不例外!作为一名合格的吃瓜群众,当然要立马去GitHub fork了一份,但是gayhub:https://github.com/openbilibili/go-common 却提示我This repository has been disabled.这个不能忍!最简单的办法就是看那些手快的已经fork了,在从他哪里fork一份过来,如果你fork失败那就直接下载,前面两种方法都不行的话可以看热心的V友们提供的分流下载地址,但是不保证原滋原味那怎么保证原汁原味呢?就有V有讨论了,看提交历史,其中有这么一段,
commit beccf3fe4313be190d655c9f0620a6b4fac0b522 (HEAD -> master, origin/master, origin/HEAD) Author: root <[email protected]> Date: Mon Apr 22 02:59:20 2019 +0000 init
但是紧接着就有不同的意见,并且复现了可以以特定的提交者信息显示,
而且这个GitHub账号openbilibili也是十个小时前全新创建的,
那么谁泄露的也就成了讨论热点,有的说是前员工,有的说是被黑了众说纷纭,我们不需要去追究谁,站方自然会去追究,我们来看一下这份源码有哪些有趣的地方。
第一个:弱口令
在源码在搜索root或者是123456,可以看到有dns和readDSN的连接是root:123456这样的简单的账号密码组合,当然地址是内网的,应该是内网的同意网关出口之类的,这也算一个安全隐患吧,要是别人进了内网或者是内网同事自扫描一波,那岂不是不可言喻...弱口令永远都是第一威胁,我在渗透测试中对于弱口令也是屡试不爽,比如拿到了后台账号或者数据库连接相关信息后,直接去连接远程桌面,有很大可能会成功,特别是前两者都为true的时候!这也表明管理员喜欢使用同一个账号密码的弱密码!
第二个:rank相关算法泄露
这些rank算法的泄露对于B站来说或许会有点麻烦,需要更新新的算法,不然大家都知道你的算法了,就很有可能据此找到相关漏洞从而加以利用,虽然B站在微博说了这是早前的代码不是最新的代码,但是后端大体的架构还是不会变化太多啊。官方微博原文:[在网上流传;经内部紧急核查;确认该部分代码;我们已经执行了主动的防御措施;确认此事件不会影响到网络安全和用户数据安全;我们已于第一时间报案;将调查其源头;],但是微博后来又自己删除了,通过看代码的最后提交日期,搜索相关的关键词比如拜年这些,基本可以确定代码肯定不是最新的,但是也是最近半年的。但是事发后貌似B站的毛老师@毛剑表示:我都不慌,你们慌什么:
第三:GO语言在后端代码中占主要
其中Go 89.7% Python 10.1%,外加一些其他的shell脚本、html和javasript这些
第四:程序员和产品经理之间的战争
在源码中搜索fuck相关词语可以看到很多类似于fuck chanpin 、fuck game、fuck article等等
第五:还有比较耿直的注释
B站的弹幕你看到的不一定都是真实的!在源码中有这么一段代码,其注释显示在中奖环节,即使你没有中奖,系统也会代你发布弹幕!从而造成一种很多人中奖的现象,而且概率是20%!
第六:B站有趣的程序员
有一首打油诗:
代码垃圾非我意, 自己动手分田地; 你若气死谁如意? 谈笑风生活长命。 powered by 主站质保团队。
第七:疑似B站在线用户统计和HotWord热词
最后,我也fork了一份,对于感兴趣的可以去下载:https://github.com/Mr-xn/openbilibili ,看看学习一下他们的GO语言代码也是不错的。如果站方要求删除的话我会删除的,有需要的自己保存。
2019-04-25更新:Github 在 bilibili 通过dmca数据版权法案申诉后 屏蔽了,故我上传我之前打包的,欢迎下载:bilibilihide-master.zip bilibil_master.zip 两个版本时间先后不一样,作为学习 GO 下载学习一下还是不错的,也不影响。
黑客Dookhtegan泄露APT 34组织工具、成员信息包括一百多条webshell 业界新闻
近期,有匿名黑客开始泄露伊朗间谍组织APT 34(OilRig 或者 HelixKitten) 所使用的黑客工具,甚至还包括团队成员及受害者数据信息等等。虽然目前来看所泄露的工具并没有永恒之蓝如此复杂,但依然引发了大量安全研究者的持续关注。 从3月份开始,有人开始以“Lab Dookhtegan”这个名字在Telegram频道 https://t.me/lab_dookhtegan 中分享这些数据,截止我发这篇文章之时,已经有接近3100+人密切关注该频道发布的内容。
其中有118条 webshell 大多都是 OA系统 或者邮箱,APT 34 组织很会挑对象啊,这些系统都是有很多的有价值的数据。我注意了一下其中包含 China 的 webshell 就有13条,包括 www.cecep.cn(中国节能环保集团公司)、generali-china.cn(中意财产保险有限公司)、exchange.bestv.com.cn(BesTV网站-BesTV百变新视界)、bdo.com.cn(BDO立信)、lswebext.sdec.com.cn(上海柴油机股份有限公司(简称“上柴股份”))、mail.swsc.com.cn(西南证券)、mail.neway.com.cn(苏州纽威阀门股份有限公司)、crccre.cn(中国铁建房地产集团有限公司),这些都是中国的公司,其中不乏一些大公司。如下图所示,其中大部分的邮箱OA系统应该都是同一套系统,估计APT 34组织有对应的 0day 或者是公司内部安全建设差,总之都是受害者,更应该反思。
更多详细的wenshell相关信息可以去这里看:https://pastebin.com/jVcZc8pR 当然文末也有目前已经放出来的所有的文件打包下载地址。
截止目前,该匿名者已经放出了6款黑客工具:
1.Glimpse(基于PowerShell的的新版木马,Palo Alto Networks命名为BondUpdater) 2.PoisonFrog(旧版BondUpdater) 3.HyperShell(称之为TwoFace的Palo Alto Networks网络外壳) 4.HighShell(另一个Web shell) 5.Fox Panel(钓鱼工具包) 6.Webmask(DNS隧道,DNSpionage背后的主要工具)
研究人员还检查了两个Web shell,发现HyperShell中名为“p”的cookie需要正确的密码才能获得访问权限。此外,Dookhtegan将所有最有意义的密码更改为“Th!sNotForFAN”。安全专家已确认这些泄露的工具和信息确实与APT 34组织有关。 Dookhtegan发布的信息还包括66名APT34组织受害者,主要是中东地区的政府机构和财务 能源公司,这与APT 34组织的先前情况一致。在有关受害者的阿联酋总统事务办公室(mopa.ae)的信息中,它还包括大约900个用户名和密码以及80多个webmail访问凭证。迪拜媒体公司的文件包括250多张优惠券。阿提哈德航空公司的信息包括10,000个用户名和明文密码,并通过Windows密码恢复工具的“高级版”破解获得。其他文件包括服务器信息 数据库转储和Mimikatz后利用工具输出数据。
目前泄露所有内容包下载地址: https://s3-eu-west-1.amazonaws.com/malware-research.org/blogposts/apt34Leak/apt34leak.7z 解压缩密码:vJrqJeJo2n005FF *
关于SQL中join的各种用法总结 技术文章
首先声明:文章来源于国外的 codeproject 我这里只是由于复习SQL的时候需要就Google搜索[可以用我个人搭建的Google搜索供大家搜索文章学习使用]了一下,找到这篇文章,再次做个简单的记录同时也方便以后的有缘人,如有侵权的地方还请来信注明,感谢原文的作者的勤劳付出,留下如此详细全面的关于SQL的join的用法。
codeproject是国外一个免费的可以公开自己写的代码与程序的优秀网站有点类似于GitHub只不过是社区版,在这个网站所有用户都可以发布自己写过的代码,程序,或者是详细的文档说明。比国内的cnblog、csdn都要好,如果要说缺点的话,就是全英文的,当然大部分还是比较容易理解的。但是codeproject也有中文区: https://www.codeproject.com/Forums/1580230/General-Chinese-Topics.aspx ,感兴趣的可以去注册玩。
我们先用一张图来看一下 LEFT JOIN、RIGHT JOIN、INNER JOIN、OUTER JOIN 等七种 join 相关的用法:
下面分开说明这七种用法,先说第一种:
1.INNER JOIN(内连接)
这是最简单,最容易理解的Join,也是最常见的。此查询将返回左表(表A)中右表(表B)中都具有匹配记录的所有记录(共同拥有的相同的部分)。此Join用法的代码大致如下:
SELECT <select_list> FROM Table_A A INNER JOIN Table_B B ON A.Key = B.Key
2.LEFT JOIN
(左连接)
LEFT JOIN 关键字会从左表 (table_name1) 那里返回所有的行,即使在右表 (table_name2) 中没有匹配的行。此Join用法的代码大致如下:
SELECT <select_list> FROM Table_A A LEFT JOIN Table_B B ON A.Key = B.Key
3.RIGHT JOIN
(右连接)
RIGHT JOIN 关键字从右表(table2)返回所有的行,即使左表(table1)中没有匹配。如果左表中没有匹配,则结果为 NULL。此Join用法的代码大致如下:
SELECT <select_list> FROM Table_A A RIGHT JOIN Table_B B ON A.Key = B.Key
4.OUTER JOIN
(外连接)
FULL OUTER JOIN 关键字只要左表(table1)和右表(table2)其中一个表中存在匹配,则返回行. FULL OUTER JOIN 关键字结合了 LEFT JOIN 和 RIGHT JOIN 的结果。此Join用法的代码大致如下:
SELECT <select_list> FROM Table_A A FULL OUTER JOIN Table_B B ON A.Key = B.Key
5.LEFT JOIN EXCLUDING INNER JOIN
(左连接-内连接)
此查询将返回左表(表A)中与右表(表B)中的任何记录都不匹配的所有记录。此Join的编写如下:
SELECT <select_list> FROM Table_A A LEFT JOIN Table_B B ON A.Key = B.Key WHERE B.Key IS NULL
6.RIGHT JOIN EXCLUDING INNER JOIN
(右连接-内连接)
此查询将返回右表(表B)中与左表(表A)中的任何记录都不匹配的所有记录。此Join的编写如下:
SELECT <select_list> FROM Table_A A RIGHT JOIN Table_B B ON A.Key = B.Key WHERE A.Key IS NULL
7.OUTER JOIN EXCLUDING INNER JOIN
(外连接-内连接)
此查询将返回左表(表A)中的所有记录以及右表(表B)中都不匹配的所有记录。我还没有需要使用这种类型的Join,但是其他的类型,我经常使用。此Join的编写如下:
SELECT <select_list> FROM Table_A A FULL OUTER JOIN Table_B B ON A.Key = B.Key WHERE A.Key IS NULL OR B.Key IS NULL
下面举一些例子:
TABLE_A PK Value ---- ---------- 1 FOX 2 COP 3 TAXI 6 WASHINGTON 7 DELL 5 ARIZONA 4 LINCOLN 10 LUCENT TABLE_B PK Value ---- ---------- 1 TROT 2 CAR 3 CAB 6 MONUMENT 7 PC 8 MICROSOFT 9 APPLE 11 SCOTCH这七种连接方式的结果如下所示:
-- INNER JOIN SELECT A.PK AS A_PK, A.Value AS A_Value, B.Value AS B_Value, B.PK AS B_PK FROM Table_A A INNER JOIN Table_B B ON A.PK = B.PK A_PK A_Value B_Value B_PK ---- ---------- ---------- ---- 1 FOX TROT 1 2 COP CAR 2 3 TAXI CAB 3 6 WASHINGTON MONUMENT 6 7 DELL PC 7 (5 row(s) affected)
-- LEFT JOIN SELECT A.PK AS A_PK, A.Value AS A_Value, B.Value AS B_Value, B.PK AS B_PK FROM Table_A A LEFT JOIN Table_B B ON A.PK = B.PK A_PK A_Value B_Value B_PK ---- ---------- ---------- ---- 1 FOX TROT 1 2 COP CAR 2 3 TAXI CAB 3 4 LINCOLN NULL NULL 5 ARIZONA NULL NULL 6 WASHINGTON MONUMENT 6 7 DELL PC 7 10 LUCENT NULL NULL (8 row(s) affected)
-- RIGHT JOIN SELECT A.PK AS A_PK, A.Value AS A_Value, B.Value AS B_Value, B.PK AS B_PK FROM Table_A A RIGHT JOIN Table_B B ON A.PK = B.PK A_PK A_Value B_Value B_PK ---- ---------- ---------- ---- 1 FOX TROT 1 2 COP CAR 2 3 TAXI CAB 3 6 WASHINGTON MONUMENT 6 7 DELL PC 7 NULL NULL MICROSOFT 8 NULL NULL APPLE 9 NULL NULL SCOTCH 11 (8 row(s) affected)
-- OUTER JOIN SELECT A.PK AS A_PK, A.Value AS A_Value, B.Value AS B_Value, B.PK AS B_PK FROM Table_A A FULL OUTER JOIN Table_B B ON A.PK = B.PK A_PK A_Value B_Value B_PK ---- ---------- ---------- ---- 1 FOX TROT 1 2 COP CAR 2 3 TAXI CAB 3 6 WASHINGTON MONUMENT 6 7 DELL PC 7 NULL NULL MICROSOFT 8 NULL NULL APPLE 9 NULL NULL SCOTCH 11 5 ARIZONA NULL NULL 4 LINCOLN NULL NULL 10 LUCENT NULL NULL (11 row(s) affected)
-- LEFT EXCLUDING JOIN SELECT A.PK AS A_PK, A.Value AS A_Value, B.Value AS B_Value, B.PK AS B_PK FROM Table_A A LEFT JOIN Table_B B ON A.PK = B.PK WHERE B.PK IS NULL A_PK A_Value B_Value B_PK ---- ---------- ---------- ---- 4 LINCOLN NULL NULL 5 ARIZONA NULL NULL 10 LUCENT NULL NULL (3 row(s) affected)
-- RIGHT EXCLUDING JOIN SELECT A.PK AS A_PK, A.Value AS A_Value, B.Value AS B_Value, B.PK AS B_PK FROM Table_A A RIGHT JOIN Table_B B ON A.PK = B.PK WHERE A.PK IS NULL A_PK A_Value B_Value B_PK ---- ---------- ---------- ---- NULL NULL MICROSOFT 8 NULL NULL APPLE 9 NULL NULL SCOTCH 11 (3 row(s) affected)
-- OUTER EXCLUDING JOIN SELECT A.PK AS A_PK, A.Value AS A_Value, B.Value AS B_Value, B.PK AS B_PK FROM Table_A A FULL OUTER JOIN Table_B B ON A.PK = B.PK WHERE A.PK IS NULL OR B.PK IS NULL A_PK A_Value B_Value B_PK ---- ---------- ---------- ---- NULL NULL MICROSOFT 8 NULL NULL APPLE 9 NULL NULL SCOTCH 11 5 ARIZONA NULL NULL 4 LINCOLN NULL NULL 10 LUCENT NULL NULL (6 row(s) affected)注:原文连接:https://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins
MySQL 在 SELECT 的同时 UPDATE 同一张表 技术文章
MySQL 不允许 SELECT FROM 后面指向用作 UPDATE 的表,有时候让人纠结。当然,有比创建无休止的临时表更好的办法。本文解释如何 UPDATE 一张表,同时在查询子句中使用 SELECT.
问题描述
假设我要 UPDATE 的表跟查询子句是同一张表,这样做有许多种原因,例如用统计数据更新表的字段(此时需要用 group 子句返回统计值),从某一条记录的字段 update 另一条记录,而不必使用非标准的语句,等等。举个例子:
create table apples(variety char(10) primary key, price int); insert into apples values('fuji', 5), ('gala', 6); update apples set price = (select price from apples where variety = 'gala') where variety = 'fuji';
错误提示是:ERROR 1093 (HY000): You can't specify target table'apples' for update in FROM clause. MySQL 手册 UPDATE documentation 这下面有说明 : “Currently, you cannot update a table and select from the same table in a subquery.”
在这个例子中,要解决问题也十分简单,但有时候不得不通过查询子句来 update 目标。好在我们有办法。
解决办法
既然 MySQL 是通过临时表来实现 FROM 子句里面的嵌套查询,那么把嵌套查询装进另外一个嵌套查询里,可使 FROM 子句查询和保存都是在临时表里进行,然后间接地在外围查询被引用。下面的语句是正确的:
update apples set price = ( select price from ( select * from apples ) as x where variety = 'gala') where variety = 'fuji';
如果你想了解更多其中的机制,请阅读 MySQL Internals Manual 相关章节。
没有解决的问题
一个常见的问题是,IN() 子句优化废品,被重写成相关的嵌套查询,有时(往往?)造成性能低下。把嵌套查询装进另外一个嵌套查询里并不能阻止它重写成相关嵌套,除非我下狠招。这种情况下,最好用 JOIN 重构查询(rewrite such a query as a join)。
另一个没解决的问题是临时表被引用多次。“装进嵌套查询” 的技巧无法解决这些问题,因为它们在编译时被创建,而上面讨论的 update 问题是在运行时。(译者注:个人认为跟文章讨论的主题没几毛钱关系)
原文地址:http://www.xaprb.com/blog/2006/06/23/how-to-select-from-an-update-target-in-mysql/
MySQL 如何查找并删除重复行? 技术文章
如何查找重复行
第一步是定义什么样的行才是重复行。多数情况下很简单:它们某一列具有相同的值。本文采用这一定义,或许你对“重复”的定义比这复杂,你需要对sql做些修改。
本文要用到的数据样本
create table test(id int not null primary key, day date not null); insert into test(id, day) values(1, '2006-10-08'); insert into test(id, day) values(2, '2006-10-08'); insert into test(id, day) values(3, '2006-10-09'); select * from test; +----+------------+ | id | day | +----+------------+ | 1 | 2006-10-08 | | 2 | 2006-10-08 | | 3 | 2006-10-09 | +----+------------+
前面两行在day字段具有相同的值,因此如何我将他们当做重复行,这里有一查询语句可以查找。查询语句使用GROUP BY子句把具有相同字段值的行归为一组,然后计算组的大小。
select day, count(*) from test GROUP BY day; +------------+----------+ | day | count(*) | +------------+----------+ | 2006-10-08 | 2 | | 2006-10-09 | 1 | +------------+----------+
重复行的组大小大于1。如何希望只显示重复行,必须使用HAVING子句,比如
select day, count(*) from test group by day HAVING count(*) > 1; +------------+----------+ | day | count(*) | +------------+----------+ | 2006-10-08 | 2 | +------------+----------+
这是基本的技巧:根据具有相同值的字段分组,然后知显示大小大于1的组。
为什么不能使用WHERE子句?
因为WHERE子句过滤的是分组之前的行,HAVING子句过滤的是分组之后的行。
如何删除重复行
一个相关的问题是如何删除重复行。一个常见的任务是,重复行只保留一行,其他删除,然后你可以创建适当的索引,防止以后再有重复的行写入数据库。
同样,首先是弄清楚重复行的定义。你要保留的是哪一行呢?第一行,或者某个字段具有最大值的行?本文中,假设要保留的是第一行——id字段具有最小值的行,意味着你要删除其他的行。
也许最简单的方法是通过临时表。尤其对于MYSQL,有些限制是不能在一个查询语句中select的同时update一个表。在我的另一篇文章中 MySQL 在 SELECT 的同时 UPDATE 同一张表(How to select from an update target in MySQL), 讲述了如何绕过这些限制。简单起见,这里只用到了临时表的方法。
我们的任务是:删除所有重复行,除了分组中id字段具有最小值的行。因此,需要找出大小大于1的分组,以及希望保留的行。你可以使用MIN()函数。这里的语句是创建临时表,以及查找需要用DELETE删除的行。
create temporary table to_delete (day date not null, min_id int not null); insert into to_delete(day, min_id) select day, MIN(id) from test group by day having count(*) > 1; select * from to_delete; +------------+--------+ | day | min_id | +------------+--------+ | 2006-10-08 | 1 | +------------+--------+
有了这些数据,你可以开始删除“脏数据”行了。可以有几种方法,各有优劣(详见我的文章many-to-one problems in SQL),但这里不做详细比较,只是说明在支持查询子句的关系数据库中,使用的标准方法。
delete from test where exists( select * from to_delete where to_delete.day = test.day and to_delete.min_id <> test.id )
如何查找多列上的重复行
有人最近问到这样的问题:
我的一个表上有两个字段b和c,分别关联到其他两个表的b和c字段。我想要找出在b字段或者c字段上具有重复值的行。
咋看很难明白,通过对话后我理解了:他想要对b和c分别创建unique索引。如上所述,查找在某一字段上具有重复值的行很简单,只要用group分组,然后计算组的大小。并且查找全部字段重复的行也很简单,只要把所有字段放到group子句。但如果是判断b字段重复或者c字段重复,问题困难得多。这里提问者用到的样本数据
create table a_b_c( a int not null primary key auto_increment, b int, c int ); insert into a_b_c(b,c) values (1, 1); insert into a_b_c(b,c) values (1, 2); insert into a_b_c(b,c) values (1, 3); insert into a_b_c(b,c) values (2, 1); insert into a_b_c(b,c) values (2, 2); insert into a_b_c(b,c) values (2, 3); insert into a_b_c(b,c) values (3, 1); insert into a_b_c(b,c) values (3, 2); insert into a_b_c(b,c) values (3, 3);
现在,你可以轻易看到表里面有一些重复的行,但找不到两行具有相同的二元组{b, c}。这就是为什么问题会变得困难了。
错误的查询语句
如果把两列放在一起分组,你会得到不同的结果,具体看如何分组和计算大小。提问者恰恰是困在了这里。有时候查询语句找到一些重复行却漏了其他的。这是他用到了查询
select b, c, count(*) from a_b_c group by b, c having count(distinct b > 1) or count(distinct c > 1);
结果返回所有的行,因为CONT(*)总是1.为什么?因为 >1 写在COUNT()里面。这个错误很容易被忽略,事实上等效于
select b, c, count(*) from a_b_c group by b, c having count(1) or count(1);
为什么?因为 (b> 1) 是一个布尔值,根本不是你想要的结果。你要的是:
select b, c, count(*) from a_b_c group by b, c having count(distinct b) > 1 or count(distinct c) > 1;
返回空结果。很显然,因为没有重复的{b,c}。这人试了很多其他的OR和AND的组合,用来分组的是一个字段,计算大小的是另一个字段,像这样
select b, count(*) from a_b_c group by b having count(distinct c) > 1; +------+----------+ | b | count(*) | +------+----------+ | 1 | 3 | | 2 | 3 | | 3 | 3 | +------+----------+
没有一个能够找出全部的重复行。而且最令人沮丧的是,对于某些情况,这种语句是有效的,如果错误地以为就是这么写法,然而对于另外的情况,很可能得到错误结果。
事实上,单纯用GROUP BY 是不可行的。为什么?因为当你对某一字段使用group by时,就会把另一字段的值分散到不同的分组里。对这些字段排序可以看到这些效果,正如分组做的那样。首先,对b字段排序,看看它是如何分组的
a | b | c |
---|---|---|
7 | 1 | 1 |
8 | 1 | 2 |
9 | 1 | 3 |
10 | 2 | 1 |
11 | 2 | 2 |
12 | 2 | 3 |
13 | 3 | 1 |
14 | 3 | 2 |
15 | 3 | 3 |
当你对b字段排序(分组),相同值的c被分到不同的组,因此不能用COUNT(DISTINCT c)来计算大小。COUNT()之类的内部函数只作用于同一个分组,对于不同分组的行就无能为力了。类似,如果排序的是c字段,相同值的b也会分到不同的组,无论如何是不能达到我们的目的的。
几种正确的方法
也许最简单的方法是分别对某个字段查找重复行,然后用UNION拼在一起,像这样:
select b as value, count(*) as cnt, 'b' as what_col from a_b_c group by b having count(*) > 1 union select c as value, count(*) as cnt, 'c' as what_col from a_b_c group by c having count(*) > 1; +-------+-----+----------+ | value | cnt | what_col | +-------+-----+----------+ | 1 | 3 | b | | 2 | 3 | b | | 3 | 3 | b | | 1 | 3 | c | | 2 | 3 | c | | 3 | 3 | c | +-------+-----+----------+
输出what_col字段为了提示重复的是哪个字段。另一个办法是使用嵌套查询:
select a, b, c from a_b_c where b in (select b from a_b_c group by b having count(*) > 1) or c in (select c from a_b_c group by c having count(*) > 1); +----+------+------+ | a | b | c | +----+------+------+ | 7 | 1 | 1 | | 8 | 1 | 2 | | 9 | 1 | 3 | | 10 | 2 | 1 | | 11 | 2 | 2 | | 12 | 2 | 3 | | 13 | 3 | 1 | | 14 | 3 | 2 | | 15 | 3 | 3 | +----+------+------+
这种方法的效率要比使用UNION低许多,并且显示每一重复的行,而不是重复的字段值。还有一种方法,将自己跟group的嵌套查询结果联表查询。写法比较复杂,但对于复杂的数据或者对效率有较高要求的情况,是很有必要的。
select a, a_b_c.b, a_b_c.c from a_b_c left outer join ( select b from a_b_c group by b having count(*) > 1 ) as b on a_b_c.b = b.b left outer join ( select c from a_b_c group by c having count(*) > 1 ) as c on a_b_c.c = c.c where b.b is not null or c.c is not null
以上方法可行,我敢肯定还有其他的方法。如果UNION能用,我想会是最简单不过的了。
原文地址:https://www.xaprb.com/blog/2006/10/09/how-to-find-duplicate-rows-with-sql/
写个了油猴脚本-freebuf文章图片去除!small 技术文章
写这个脚本的原因就是我发现freebuf的文章里的图片后缀都会跟一个 !small 后缀,我想网站初心可能是为了对付爬虫吧,恶意爬虫爬去文章文字和图片,但是对于我这种懒虫,不喜欢点击一下放大去看图,而是比较喜欢文章的图片就是页面最佳尺寸,简单的研究了一下,发现去掉文章里的图片的 !small 后缀后,文章图片默认就会显示最佳尺寸了!简直Nice啊!但是每次这么去手动修改太麻烦了,如果文章图片太多,那岂不是要累死?于是这个脚本就出来了!效果如下的动图演示:
使用:前提是在油猴脚本支持的浏览器(比如chrome,Firefox这些现代浏览器),在油猴插件里面自己粘贴我发布在GitHub仓库的代码或者是从Greasy Fork 在线下载安装 (强烈推荐)