什么是构建MySQL查询的结构化方法?

Ave*_*ery 7 mysql sql

我认为自己在理解和操纵C-ish语言方面相当称职; 我想出一个算法并用任何C语言实现它都不是问题.

编写SQL(在我的特定情况下,MySQL)查询时遇到了极大的困难.对于非常简单的查询,这不是问题,但对于复杂的查询,我会因为不知道从哪里开始而感到沮丧.阅读MySQL文档很困难,主要是因为语法描述和解释组织得不是很好.

例如,SELECT文档遍布地图:它从看起来像psuedo-BNF开始,但随后(因为聚合描述的文本不可点击......就像select_expr)它很快就会陷入这种令人沮丧的尝试通过打开多个浏览器窗口将语法拼凑在一起.

够了抱怨.

我想知道人们如何逐步开始构建复杂的MySQL查询.这是一个具体的例子.我有三张桌子.我想要SELECT一组具有以下特征的行:

userInfouserProgram表,我要选择userName,isApprovedmodifiedTimestamp领域,UNION他们为一组.从这一组我想ORDER通过modifiedTimestamp采取MAX(modifiedTimestamp)为每个用户(即应该只有一个唯一行userName,并与用户名关联应该是尽可能高的时间戳).

user表,我想匹配firstName,并lastName与该关联userName,以便它看起来是这样的:

+-----------+----------+----------+-------------------+
| firstName | lastName | userName | modifiedTimestamp |
+-----------+----------+----------+-------------------+
| JJ        | Prof     | jjprofUs |        1289914725 |
| User      | 2        | user2    |        1289914722 |
| User      | 1        | user1    |        1289914716 |
| User      | 3        | user3    |        1289914713 |
| User      | 4        | user4    |        1289914712 |
| User      | 5        | user5    |        1289914711 |
+-----------+----------+----------+-------------------+
Run Code Online (Sandbox Code Playgroud)

我最接近的是一个如下所示的查询:

(SELECT firstName, lastName, user.userName, modifiedTimestamp 
FROM user, userInfo 
WHERE user.userName=userInfo.userName) 

UNION 

(SELECT firstName, lastName, user.userName, modifiedTimestamp 
FROM user, userProgram 
WHERE user.userName=userProgram.userName)

ORDER BY modifiedTimestamp DESC;
Run Code Online (Sandbox Code Playgroud)

我觉得我很近,但我不知道从哪里开始,或者即使我正在以正确的方式思考这个问题.

> user
+--------------------+--------------+------+-----+---------+-------+
| Field              | Type         | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+-------+
| userName           | char(8)      | NO   | PRI | NULL    |       |
| firstName          | varchar(255) | NO   |     | NULL    |       |
| lastName           | varchar(255) | NO   |     | NULL    |       |
| email              | varchar(255) | NO   | UNI | NULL    |       |
| avatar             | varchar(255) | YES  |     | ''      |       |
| password           | varchar(255) | NO   |     | NULL    |       |
| passwordHint       | text         | YES  |     | NULL    |       |
| access             | int(11)      | NO   |     | 1       |       |
| lastLoginTimestamp | int(11)      | NO   |     | -1      |       |
| isActive           | tinyint(4)   | NO   |     | 1       |       |
+--------------------+--------------+------+-----+---------+-------+

> userInfo
+-------------------+------------+------+-----+---------+-------+
| Field             | Type       | Null | Key | Default | Extra |
+-------------------+------------+------+-----+---------+-------+
| userName          | char(8)    | NO   | MUL | NULL    |       |
| isApproved        | tinyint(4) | NO   |     | 0       |       |
| modifiedTimestamp | int(11)    | NO   |     | NULL    |       |
| field             | char(255)  | YES  |     | NULL    |       |
| value             | text       | YES  |     | NULL    |       |
+-------------------+------------+------+-----+---------+-------+

> userProgram
+-------------------+--------------+------+-----+---------+-------+
| Field             | Type         | Null | Key | Default | Extra |
+-------------------+--------------+------+-----+---------+-------+
| userName          | char(8)      | NO   | PRI | NULL    |       |
| isApproved        | tinyint(4)   | NO   | PRI | 0       |       |
| modifiedTimestamp | int(11)      | NO   |     | NULL    |       |
| name              | varchar(255) | YES  |     | NULL    |       |
| address1          | varchar(255) | YES  |     | NULL    |       |
| address2          | varchar(255) | YES  |     | NULL    |       |
| city              | varchar(50)  | YES  |     | NULL    |       |
| state             | char(2)      | YES  | MUL | NULL    |       |
| zip               | char(10)     | YES  |     | NULL    |       |
| phone             | varchar(25)  | YES  |     | NULL    |       |
| fax               | varchar(25)  | YES  |     | NULL    |       |
| ehsChildren       | int(11)      | YES  |     | NULL    |       |
| hsChildren        | int(11)      | YES  |     | NULL    |       |
| siteCount         | int(11)      | YES  |     | NULL    |       |
| staffCount        | int(11)      | YES  |     | NULL    |       |
| grantee           | varchar(255) | YES  |     | NULL    |       |
| programType       | varchar(255) | YES  |     | NULL    |       |
| additional        | text         | YES  |     | NULL    |       |
+-------------------+--------------+------+-----+---------+-------+
Run Code Online (Sandbox Code Playgroud)

Ale*_*noy 1

根据我从您的问题中了解到的,您似乎需要一个相关查询,如下所示:

(SELECT firstName, lastName, user.userName, modifiedTimestamp 
FROM user, userInfo ui1
WHERE user.userName=userInfo.userName
AND modifiedtimestamp=(select max(modifiedtimestamp) from userInfo ui2 where ui1.userName=ui2.userName)) 

UNION 

(SELECT firstName, lastName, user.userName, modifiedTimestamp 
FROM user, userProgram up1
WHERE user.userName=userProgram.userName
AND modifiedtimestamp=(select max(modifiedtimestamp) from userProgram up2 where up1.userName=up2.userName))
ORDER BY modifiedTimestamp DESC;
Run Code Online (Sandbox Code Playgroud)

那么,我要继续得到这个结果吗?关键是:清楚地表达你想要检索的信息,不要走捷径。

步骤1:在数据库的不同表中选择我需要的字段。这就是 SELECT 和 FROM 之间的内容。看起来很明显,但当涉及到总和或计数等聚合函数时,它就变得不那么明显了。在这种情况下,您必须说,例如“我需要 userInfo 中每个名字的行数”。请参阅下面的 GROUP BY。

步骤2:知道你需要的字段,编写不同对应表之间的连接。这是一个简单的...

第三步:表达你的条件。它可以很简单,例如您想要来自 userName="RZEZDFGBH" 的用户数据,或者更复杂,例如您的情况:如果您只想要最近修改的时间戳,那么制定它的方法以便您可以完成任务,是“使修改后的时间戳等于最近的修改后的时间戳”(这就是你很容易走捷径而错过要点的地方)

步骤 4:如果您有聚合,则需要设置 GROUP BY 语句。例如,如果计算 userInfo 中每个名字的所有行,则应编写“GROUP BY firstName”:

SELECT firstName,count(*) FROM userInfo GROUP BY firstName
Run Code Online (Sandbox Code Playgroud)

这将为您提供表中每个不同名字的条目数。

第五步:具备条件。这些是总量的条件。在前面的示例中,如果您只想获取表中超过 5 行的firstName 的数据,您可以编写SELECT firstName,count(*) FROM userInfo GROUP BY firstName HAVING count(*)>5

第6步:使用ORDER BY排序。挺容易...

这只是一个简短的总结。还有很多很多东西有待发现,但是在这里写完整的 SQL 课程太长了......但希望它能有所帮助!