假设有一张桌子
演示
使用这些数据:
ID | 用户身份 | 标题 | 数据 |
---|---|---|---|
1 | 1 | 日期 | 01-01-2021 |
2 | 1 | 颜色 | 红色的 |
3 | 2 | 日期 | |
4 | 2 | 颜色 | 黄色 |
5 | 3 | 日期 | 04-01-2021 |
6 | 3 | 颜色 | 红色的 |
5 | 4 | 日期 | 04-01-2021 |
6 | 4 | 颜色 | 粉色的 |
7 | 5 | 日期 | 02-01-2021 |
8 | 5 | 颜色 | 粉色的 |
7 | 6 | 日期 | 08-01-2021 |
8 | 6 | 颜色 | 粉色的 |
如果行日期的数据是空的,颜色还没有被拾取。
我需要在网站 php 页面上查看的信息概述是:
获得的 RED:2
总 RED:2
黄色拾取:0
总黄色:1
粉红色拾取:3
总粉红色:3
您好,欢迎到论坛!
您的架构需要彻底彻底改革。这张图片给出了一些关于它有什么问题的想法:
您使用了 EAV(实体-属性-值)数据库设计反模式 - 搜索Joe Celko、Bill Karwin和其他人(以及其中的链接)关于该主题的著作。
此外,非常重要的是,您应该将
VARCHAR()
s 存储为VARCHAR()
s 并将DATE
s 存储为DATE
s - 当您阅读 EAV 时您会看到这一点 - 数据类型超出了窗口,这意味着查询优化器无法生成最佳计划。这也适用于其他类型。你可以在这里看到这个效果:
结果:
正确的数据类型很重要的原因之一!即使您必须将日期存储为字符串(我意识到程序员会受到限制),您也应该使用ISO 日期格式(即 YYYY-MM-DD)。
TL;DR - 答案!
如果您只想要答案,那么它是:
结果:
它还具有成为提议中最快查询的优点 - 请参阅
PROFILING
下面的部分!处理架构:
你应该做的是(参见这里的小提琴- 改编自@Akina's - 我添加了一件收集的黄色服装。我不知道该
id
专栏发生了什么,此后我忽略了它)。因此,您创建了一个
VIEW
- 如果由于其他限制而无法更改架构 - 我很欣赏 DBA/程序员并不总是(完全)控制他们的环境。看法:
桌子:
然后您对表格的查询(也可以在视图上 - 参见小提琴)将非常简单:
结果(所有查询相同):
现在,为什么,您可能会问我在这里使用“复杂”而不是Akina 的答案
SUM(CASE...
相对“简单” 。如果您尝试使用 PostgreSQL 运行他的小提琴(请参阅此处),它会失败。该结构是特定于 MySQL 的,而另一个适用于 PostgreSQL、SQLServer 和 MySQL!如果有疑问 - 在 PostgreSQL 上测试 - 如果它在那里不起作用,通常会有一些可疑的事情发生!SUM(t1.data IS NOT NULL)...
SUM(... IS NOT NULL)
如果您想(或有义务)坚持使用当前的模式,请运行以下命令:
结果 - 添加了一个百分比收集字段!
我做了一个性能分析 - 见小提琴 - 使用分析 - 检查手册:
运行您的查询
结果(显示的典型结果 - 运行了几次 - 可能会有所不同!查询可能会被截断):
基于表的查询非常频繁地具有最短的持续时间(大约 90% 的时间 - 我们不知道 dbfiddle 服务器的其余部分发生了什么)。基于表的查询的查询计划比其他查询计划短得多(
EXPLAIN ANALYZE
- 见小提琴) - 好的经验法则,计划越短,查询越快!如果你想使用标准 SQL(你应该!),你可以使用这个命令(见小提琴的底部) - 你可以发出
SET sql_mode='ANSI';
命令 - 从前面提到的 Bill Karwin 的答案这里。我把它作为练习留给读者,将现在有效的日期放入上面的 SQL 中——它应该与 MySQL 特定的构造完全相同——你可以在 PostgreSQL fiddle 中看到这一点。
我还留给您为大型数据集的必要字段添加索引 - 如果您遇到问题,请在此处返回一个新问题,其中包含指向此问题的链接!
EXPLAIN ANALYZE
在这方面应该给出一些提示!小提琴