- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个非常复杂的查询,它在 CASE 语句中使用了一些子查询。
对于这个问题,不需要完整的查询,它只会阻止人们快速进入问题。
所以这篇文章使用伪代码来处理。如果需要,我可以发布查询,但它是一个怪物,对这个问题没有用。
我想要的是 CASE 语句中的可缓存子查询。
SELECT * FROM posts posts
INNER JOIN posts_shared_to shared_to
ON shared_to.post_id = posts.post_id
INNER JOIN channels.channels
ON channels.channel_id = shared_to.channel_id
WHERE posts.parent_id IS NULL
AND MATCH (post.text) AGAINST (:keyword IN BOOLEAN MODE)
AND CASE(
WHEN channel.read_access IS NULL THEN 1
WHEN channel.read_access = 1 THEN
(
SELECT count(*) FROM channel_users
WHERE user_id = XXX AND channel_id = channels.channel_id
)
WHEN shared_to.read_type = 2 THEN
(
/* another subquery with a join */
/* check if user is in friendlist of post_author */
)
ELSE 0
END;
)
GROUP BY post.post_id
ORDER BY post.post_id
DESC LIMIT n,n
如上所述,这只是一个简化的伪代码。
MySql EXPLAIN 说 CASE 中所有使用的子查询都是 DEPENDENT,这意味着(如果我是正确的)它们需要每次运行并且不被缓存。
欢迎任何有助于加快查询速度的解决方案。
编辑部分:现在真正的查询看起来像这样:
SELECT a.id, a.title, a.message AS post_text, a.type, a.date, a.author AS uid,
b.a_name as name, b.avatar,
shared_to.to_circle AS circle_id, shared_to.root_circle,
c.circle_name, c.read_access, c.owner_uid, c.profile,
MATCH(a.title,a.message) AGAINST (:keyword IN BOOLEAN MODE) AS score
FROM posts a
/** get userdetails for post_author **/
JOIN authors b ON b.id = a.author
/** get circles posts was shared to **/
JOIN posts_shared_to shared_to ON shared_to.post_id = a.id AND shared_to.deleted IS NULL
/**
* get circle_details note: at the moment shared_to can contain NULL and 1 too and doesnt need to be a circle_id
* if to_circle IS NULL post was shared public
* if to_circle = 1 post was shared to private circles
* since we use md5 keys as circle ids this can be a string insetad of (int) ... ugly..
*
**/
LEFT JOIN circles c ON c.circle_id = shared_to.to_circle
/*AND c.circle_name IS NOT NULL */
AND ( c.profile IS NULL OR c.profile = 6 OR c.profile = 1 )
AND c.deleted IS NULL
LEFT JOIN (
/** if post is within a channel that requires membership we use this to check if requesting user is member **/
SELECT COUNT(*) users_count, user_id, circle_id FROM circles_users
GROUP BY user_id, circle_id
) counts ON counts.circle_id = shared_to.to_circle
AND counts.user_id = :me
LEFT JOIN (
/** if post is shared private we check if requesting users exists within post authors private circles **/
SELECT count(*) in_circles_count, ci.owner_uid AS circle_owner, cu1.user_id AS user_me
FROM circles ci
INNER JOIN circles_users cu1 ON cu1.circle_id = ci.circle_id
AND cu1.deleted IS NULL
WHERE ci.profile IS NULL AND ci.deleted IS NULL
GROUP BY user_me, circle_owner
) users_in_circles ON users_in_circles.user_me = :me
AND users_in_circles.circle_owner = a.id
/** make sure post is a topic **/
WHERE a.parent_id IS NULL AND a.deleted IS NULL
/** search title and post body **/
AND MATCH (a.title,a.message) AGAINST (:keyword IN BOOLEAN MODE)
AND (
/** own circle **/
c.owner_uid = :me
/** site member read_access ( this query is for members, for guests we use a different query ) **/
OR ( c.read_access = 1 OR c.read_access = "1" )
/** public read_access **/
OR ( shared_to.to_circle IS NULL OR ( c.read_access IS NULL AND c.owner_uid IS NOT NULL ) )
/** channel/circle member read_access**/
OR ( c.read_access = 3 OR c.read_access = "3" AND counts.users_count > 0 )
/** for users within post creators private circles **/
OR (
(
/** use shared_to to determine if post is private **/
shared_to.to_circle = "1" OR shared_to.to_circle = 1
/** use circle settings to determine global privacy **/
OR ( c.owner_uid IS NOT NULL AND c.read_access = 2 OR c.read_access = "2" )
) AND users_in_circles.circle_owner = a.author AND users_in_circles.user_me = :me
)
)
GROUP BY a.id ORDER BY a.id DESC LIMIT n,n
问题:这真的是更好的方法吗?如果我查看派生表可以包含多少行,我不确定。
也许有人可以像@Ollie-Jones 提到的那样帮助我更改查询:
SELECT stuff, stuff, stuff
FROM (
SELECT post.post_id
FROM your whole query
ORDER BY post_id DESC
LIMIT n,n
) ids
JOIN whatever ON whatever.post_id = ids.post_id
JOIN whatelse ON whatelse
对不起,如果这听起来很懒惰,但我并不是一个真正的 mysqlguy,多年来我一直为构建这个查询而头疼。 :D
最佳答案
消除依赖子查询的最佳方法是重构它,使其成为一个虚拟表(一个独立的子查询),然后将其连接或左连接到您的其余表。
在你的案例中,你有
SELECT count(*) FROM channel_users
WHERE user_id = XXX AND channel_id = channels.channel_id
因此,它的独立子查询转换是
SELECT COUNT(*) users_count,
user_id, channel_id
FROM channel_users
GROUP BY user_id, channel_id
您是否看到该虚拟表如何为 user_id
和 channel_id
值的每个不同组合包含一行?每行都有您需要的 users_count
值。然后,您可以像这样将其 JOIN 到您的其余查询中。 (注意 INNER JOIN === JOIN 在 MySQL 中,所以我使用 JOIN 来缩短它。)
SELECT * FROM posts posts
JOIN posts_shared_to shared_to ON shared_to.post_id = posts.post_id
JOIN channels.channels ON channels.channel_id = shared_to.channel_id
LEFT JOIN (
SELECT COUNT(*) users_count,
user_id, channel_id
FROM channel_users
GROUP BY user_id, channel_id
) counts ON counts.channel_id = shared_to.channel_id
AND counts.user_id = channels.user_id
LEFT JOIN ( /* your other refactored subquery */
) friendcounts ON whatever
WHERE posts.parent_id IS NULL
AND channels.user_id = XXX
AND MATCH (post.text) AGAINST (:keyword IN BOOLEAN MODE)
AND ( channel.read_access IS NULL
OR (channel.read_access = 1 AND counts.users_count > 0)
OR (shared_to.read_type = AND friendcount.users_count > 0)
)
GROUP BY post.post_id
ORDER BY post.post_id DESC
LIMIT n,n
MySQL 查询规划器通常足够智能,可以为每个独立的子查询生成适当的子集。
专业提示: SELECT lots of columns ... ORDER BY something LIMIT n
通常被认为是一种浪费的反模式。它会降低性能,因为它会对一大堆数据列进行排序,然后丢弃大部分结果。
专业提示: SELECT *
在 JOIN 查询中也是一种浪费。如果您提供结果集中实际需要的列的列表,情况会好得多。
所以,你可以再次重构你的查询来做
SELECT stuff, stuff, stuff
FROM (
SELECT post.post_id
FROM your whole query
ORDER BY post_id DESC
LIMIT n,n
) ids
JOIN whatever ON whatever.post_id = ids.post_id
JOIN whatelse ON whatelse.
我们的想法是只对 post_id
值进行排序,然后使用 LIMITed 子集来提取您需要的其余数据。
关于mysql - 如何防止 CASE WHEN x THE(子查询)中的依赖子查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36516436/
我有三张 table 。表 A 有选项名称(即颜色、尺寸)。表 B 有选项值名称(即蓝色、红色、黑色等)。表C通过将选项名称id和选项名称值id放在一起来建立关系。 我的查询需要显示值和选项的名称,而
在mysql中,如何计算一行中的非空单元格?我只想计算某些列之间的单元格,比如第 3-10 列之间的单元格。不是所有的列...同样,仅在该行中。 最佳答案 如果你想这样做,只能在 sql 中使用名称而
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 7 年前。 Improve this ques
我正在为版本7.6进行Elasticsearch查询 我的查询是这样的: { "query": { "bool": { "should": [ {
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 7 年前。 Improve this ques
是否可以编写一个查询来检查任一子查询(而不是一个子查询)是否正确? SELECT * FROM employees e WHERE NOT EXISTS (
我找到了很多关于我的问题的答案,但问题没有解决 我有表格,有数据,例如: Data 1 Data 2 Data 3
以下查询返回错误: 查询: SELECT Id, FirstName, LastName, OwnerId, PersonEmail FROM Account WHERE lower(PersonEm
以下查询返回错误: 查询: SELECT Id, FirstName, LastName, OwnerId, PersonEmail FROM Account WHERE lower(PersonEm
我从 EditText 中获取了 String 值。以及提交查询的按钮。 String sql=editQuery.getText().toString();// SELECT * FROM empl
我有一个或多或少有效的查询(关于结果),但处理大约需要 45 秒。这对于在 GUI 中呈现数据来说肯定太长了。 所以我的需求是找到一个更快/更高效的查询(几毫秒左右会很好)我的数据表大约有 3000
这是我第一次使用 Stack Overflow,所以我希望我以正确的方式提出这个问题。 我有 2 个 SQL 查询,我正在尝试比较和识别缺失值,尽管我无法将 NULL 字段添加到第二个查询中以识别缺失
什么是动态 SQL 查询?何时需要使用动态 SQL 查询?我使用的是 SQL Server 2005。 最佳答案 这里有几篇文章: Introduction to Dynamic SQL Dynami
include "mysql.php"; $query= "SELECT ID,name,displayname,established,summary,searchlink,im
我有一个查询要“转换”为 mysql。这是查询: select top 5 * from (select id, firstName, lastName, sum(fileSize) as To
通过我的研究,我发现至少从 EF 4.1 开始,EF 查询上的 .ToString() 方法将返回要运行的 SQL。事实上,这对我来说非常有用,使用 Entity Framework 5 和 6。 但
我在构造查询来执行以下操作时遇到问题: 按activity_type_id过滤联系人,仅显示最近事件具有所需activity_type_id或为NULL(无事件)的联系人 表格结构如下: 一个联系人可
如何让我输入数据库的信息在输入数据 5 分钟后自行更新? 假设我有一张 table : +--+--+-----+ |id|ip|count| +--+--+-----+ |
我正在尝试搜索正好是 4 位数字的 ID,我知道我需要使用 LENGTH() 字符串函数,但找不到如何使用它的示例。我正在尝试以下(和其他变体)但它们不起作用。 SELECT max(car_id)
我有一个在 mysql 上运行良好的 sql 查询(查询 + 连接): select sum(pa.price) from user u , purchase pu , pack pa where (
我是一名优秀的程序员,十分优秀!