标签: subquery

子查询单独运行非常快,但加入时非常慢

ypercube 解决了这个问题。子查询是完全没有必要的,整个事情都可以使用普通连接。不过,MySQL 的优化器无法使用我的原始查询仍然很奇怪。有关问题和许多详细信息,请参见下文。在我的问题底部加上一个完整的解决方案。它基于 ypercube 的答案。

每个子查询都非常快,不到 1 秒。加入了 5-6 个子查询(一些LEFT,一些INNER),时间增加到 400 秒。

我用于测试的整体查询仅返回 441 行。

我尝试将每个子查询放在“CREATE TABLE”查询中。每一个都在不到 1 秒的时间内完成。然后我使用那些新创建的表重新执行外部查询,它的运行时间也远低于 1 秒。所以连接没有实际问题。我id为我创建的表添加了索引。所有表都在匹配id= 上连接id

如何让 MySQL 高效地执行查询?我必须使用临时表吗?我已经编写了一堆 PHP 代码来将多个子查询连接放在一起,所以如果可能的话,我宁愿弄清楚如何使其工作。

我尝试使用“STRAIGHT_JOIN”关键字并删除外部ORDER BY. 这将查询时间减少到 90 秒。但我应该最多获得 1 秒。

我试过STRAIGHT_JOINORDER BY,花了 235 秒。所以看起来外部ORDER BY是一个主要的性能问题。

编辑:

使用临时表进行测试。查询运行速度非常快。但是必须有一种方法可以让 mysql 使用 JOINS 快速完成它。

此外,慢查询日志显示:

Rows_examined: 484006914
Run Code Online (Sandbox Code Playgroud)

4.84 亿行看起来像笛卡尔积。为什么要检查这么多行?

查询具有以下结构:

SELECT t0.`id`, t1.`length`, t2.`height`, t3.`family`
FROM
`products` t0
INNER JOIN
( …
Run Code Online (Sandbox Code Playgroud)

mysql join optimization subquery

7
推荐指数
1
解决办法
2万
查看次数

更改非相关子查询的访问方法

甲骨文 11g R2

不幸的是,我们的应用程序具有每行安全“功能”。我们有一个看起来像这样的查询:

坏,慢:

SELECT someRow, someOtherRow
FROM bigTableA a
WHERE EXISTS (
  SELECT 0 FROM bigTableA_securitymapping b 
  WHERE b.PrimaryKeyTableA = a.PrimaryKeyTableA AND
       b.accesscode in (SELECT accesscode 
                              FROM accesscodeView 
                              WHERE user = :someUserID)
)
Run Code Online (Sandbox Code Playgroud)

上有一个唯一索引bigTableA_securitymapping(PrimaryKeyTableA,accesscode)

accesscodeView有可能返回多个accesscode给定用户,所以它必须是IN()=

问题是此查询忽略了唯一索引bigTableA_securitymapping并选择执行全表扫描。

如果我将 the 更改IN()为 an=那么它会UNIQUE SCAN在唯一索引上执行 abigTableA_securitymapping并且大约快 50 倍。

好,快但不可能:

SELECT someRow, someOtherRow
    FROM bigTableA a
    WHERE EXISTS (
      SELECT 0 FROM bigTableA_securitymapping …
Run Code Online (Sandbox Code Playgroud)

oracle subquery

7
推荐指数
1
解决办法
111
查看次数

子查询无法从超级查询的连接中找到列

我在 SQL 方面遇到了一些麻烦:基本上,我试图获取一个结果集,其中包含向员工提出的所有问题的总和(按公司分组),并添加手动添加项目的“onetime_items”不同的表。

我目前有这个 SQL 语句(我使用的是 MySQL):

SELECT 
CONCAT_WS(
    ', ', count(DISTINCT CONCAT(emailaddress, '_', e.id)),
    (
        SELECT GROUP_CONCAT(items SEPARATOR '; ') as OneTimeItems
        FROM ( 
            SELECT CONCAT_WS(
                ': ', oi.item_name, SUM(oi.item_amount)
            ) items 
            FROM onetime_item oi 
            WHERE oi.company_id = e.company_id
            AND oi.date BETWEEN '2015-12-01'
            AND LAST_DAY('2015-12-01') 
            GROUP BY oi.item_name 
        ) resulta
    )
) as AllItems,
e.id,
LEFT(e.firstname, 1) as voorletter,
e.lastname
FROM question q 
LEFT JOIN employee e ON q.employee_id = e.id 
WHERE 1=1 
AND YEAR(created_at) = '2015'
AND MONTH(created_at) …
Run Code Online (Sandbox Code Playgroud)

mysql join subquery

7
推荐指数
1
解决办法
8241
查看次数

使用子查询和 IN 子句查询性能

我正在尝试从历史表中为多个设备(唯一序列号)选择一系列数据,并想知道为什么以下查询的时间差异如此之大:

基本上我试图使用 IN 子句来指示我想要获取数据的项目。如果我对 IN 子句中的项目进行“硬编码”,则查询速度很快,如果我使用子查询或连接来选择项目,则性能很差。

此查询在 0.15 秒内完成并返回 7382 行。

SELECT `readings`.* FROM `readings`
WHERE
  (SerialNumber IN ('091146000121', *snip 25*, '091146000556'))
AND (readings.time >= 1325404800)
AND (readings.time < 1326317400)
ORDER BY `time` ASC
Run Code Online (Sandbox Code Playgroud)

使用子查询重写以获取序列号的相同查询需要 30 多秒,并且似乎大部分时间都处于 Preparing 状态。它返回与第一个查询相同的数据。

SELECT `readings`.* FROM `readings`
WHERE
  (SerialNumber IN (SELECT `boards`.`id` AS `SerialNumber` FROM `boards` WHERE (siteId = '1')))
AND (readings.time >= 1325404800)
AND (readings.time < 1326317400)
ORDER BY `time` ASC
Run Code Online (Sandbox Code Playgroud)

子查询返回与第一个查询中相同的值,但如前所述,这需要更长的时间来运行。 它们在功能上不是等效的吗?

这是两个查询的解释:

+----+-------------+----------+-------+---------------+---------+---------+------+------+-----------------------------+
| id | select_type | table    | type …
Run Code Online (Sandbox Code Playgroud)

mysql performance subquery

6
推荐指数
1
解决办法
1万
查看次数

检索尚未分配到工作的车辆驾驶员的数据

过去 24 小时都在为某事挣扎。需要一些天才来发光。我正在尝试为驱动程序显示每周工作循环/日志,它将显示:

  • 尚未分配给司机的工作
  • 已分配给司机的工作
  • 如果作业已分配给驱动程序,则显示当天可用的驱动程序
  • 如果当天没有工作,则显示所有可用驱动程序的列表

最后2点是我真正挣扎的地方。

我有以下表格:

drivers ('driver_id', 'driver_name')

vehicles ('vehicle_id', 'vehicle_make', 'vehicle_model')

jobs ('job_id', 'collection_address', 'collection_datetime', 'delivery_address', 'deliver_datetime', 'driver_id', 'vehicle_id') 
Run Code Online (Sandbox Code Playgroud)

我附上了下面的输出屏幕:

在此处输入图片说明

例如,如果您查看 23/09/2016,司机 Keith 正在工作,但 Nick 有空。但是,如果我执行子查询,它会显示两个驱动程序,这不是正确的结果。我的 SQL 语句如下,如果有人可以提供帮助,我将不胜感激。

    SELECT listofdays.job_date, j.job_id, IF( j.driver_id > 0 AND j.job_id > 0, (SELECT driver_name FROM t_drivers WHERE driver_id = j.driver_id LIMIT 1), '') as job_driver, IF( j.vehicle_id > 0, (SELECT vehicle_reg FROM t_vehicles WHERE vehicle_id = j.vehicle_id LIMIT 1), 'no') as job_vehicle, j.collection_town, j.collection_postcode, j.delivery_town, j.delivery_postcode, j.job_status
 FROM …
Run Code Online (Sandbox Code Playgroud)

mysql performance subquery select query-performance

6
推荐指数
1
解决办法
106
查看次数

将值传递给嵌套子查询

我有以下查询(为简洁起见已删除),其目的是创建w8用于对结果进行排序的值:

SELECT elements.id, [ ... ],
(SELECT 
    COALESCE(craft_w8_a.weight, 0) + COALESCE(SUM(craft_w8_b.weight), 0) 
    FROM `craft_w8` `craft_w8_a`
    LEFT JOIN `craft_w8` `craft_w8_b` 
        ON craft_w8_b.elementId
        IN ( SELECT targetId FROM `craft_relations`
                WHERE fieldId IN (15, 16)
                  AND sourceId = elements.id)
    WHERE craft_w8_a.elementId = elements.id
) as w8
FROM `craft_elements` `elements`
[ ... ]
GROUP BY `elements`.`id`
ORDER BY `w8` DESC, `name` ASC LIMIT 100
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是第二个嵌套子查询(左连接中的那个)无法elements.id从初始选择中找到该列。

从我发现在 SQL 中搜索只传递一级深度的值,我一直无法找到合适的解决方法。

是否可以强制 SQL 传递比一级更深的值?或者有没有办法修改查询以不使用另一个子查询,但仍然得到相同的结果?

对不起,如果我做任何愚蠢的事情或遗漏了任何明显的东西,SQL 不是我的强项!

mysql subquery

6
推荐指数
1
解决办法
3万
查看次数

select语句列中的MYSQL子查询

select(投影)的列字段中的子查询如何与主查询的结果配对?形式:

 SELECT id,email,(SELECT name From Names WHERE Names.id=Users.id) as name
 FROM Users
Run Code Online (Sandbox Code Playgroud)

子查询是从 , 的输出中每行执行一次SELECT id,email FROM Users,因此应该LIMIT 1在子查询上使用(因为子查询中只有 1 行可以与主查询中的一行配对),还是子查询运行一次,并且然后每个结果都与来自 的相应行配对SELECT id,email FROM Users,很像等效连接:SELECT id,email,name FROM Users JOIN Names ON Users.id=Names.id

mysql subquery

6
推荐指数
2
解决办法
5万
查看次数

为什么使用相关子查询的不正确 JOIN 会慢得多

我在做一些相当轻量级的数据按摩/清洁跑进其中使用相关子查询(可能是错误的)JOIN的一个版本跑了太大的问题很多比我相信这是正确的慢。我不问如何查询(我相信现在我已经得到了正确的),但我想知道为什么慢版是如此缓慢。

问题

该域是一个相当简单的数据库,用于管理彩票辛迪加(记录会员付款、玩的游戏和获胜)。在转向新引擎 (SQLite) 时,我正在尝试清理数据并改进表的结构。

现有_Winnings表格记录了赢得的金额和日期以及“游戏类型”(可以玩多个游戏):

CREATE TABLE [_Winnings](
    [ID]                integer primary key not null,
    [WinDate]           date,
    [Amount]            integer,
    [GameType]          integer references _Games(ID)
);
CREATE INDEX [_WinningsIndex] on _Winnings(GameType) ;
Run Code Online (Sandbox Code Playgroud)

主要问题是没有链接(除了获胜日期)到实际玩的游戏。这些记录已经被迁移,现在保存在一个EventHistory表中:

CREATE TABLE [EventHistory](
    [ID]                integer primary key not null,
    [EventType]         integer references Events(ID),
    [GameType]          integer references Games(ID),
    [EventDate]         date
);
CREATE INDEX [EventHistoryEventIndex] on EventHistory(EventType) ;
CREATE INDEX [EventHistoryGameIndex]  on EventHistory(GameType) ;
CREATE INDEX [EventHistoryDateIndex]  on EventHistory(EventDate) ;
Run Code Online (Sandbox Code Playgroud)

三个表_Games, …

sqlite performance subquery query-performance

6
推荐指数
1
解决办法
133
查看次数

为什么 SQL Server 将它的 (JSON) 响应拆分为多行?

我正在尝试构建一个查询,该查询会生成一个由 SQL Server 生成的 JSON 对象。我发现我可以使用子查询用包含问题列表的 JSON 字符串填充字段(在本例中为问题字段)。

下面是查询:

SELECT
    quizzes.id AS 'id',
    quizzes.name AS 'name',
    quizzes.description AS 'description',
    quizzes.instructions AS 'instructions',
    author.id AS 'author.id',
    author.midas AS 'author.midas',
    author.first_name AS 'author.first_name',
    author.last_name AS 'author.last_name',
    author.email AS 'author.email',
    author.tel AS 'author.tel',
    author.department_name AS 'author.department_name',
    author.created_at AS 'author.created_at',
    author.last_updated AS 'author.last_updated',
    course.id AS 'course.id',
    course.name AS 'course.name',
    course.description AS 'course.description',
    course.crn AS 'course.crn',
    instructor.id AS 'course.instructor.id',
    instructor.midas AS 'course.instructor.midas',
    instructor.first_name AS 'course.instructor.first_name',
    instructor.last_name AS 'course.instructor.last_name',
    instructor.email AS 'course.instructor.email',
    instructor.tel AS 'course.instructor.tel',
    instructor.department_name …
Run Code Online (Sandbox Code Playgroud)

sql-server query subquery json

6
推荐指数
1
解决办法
729
查看次数

WHERE 子句中未使用的列

我在我们的代码库中找到了这个查询:

DELETE FROM "Foo"
WHERE ("Foo"."Id", "Foo"."CreatedAt")
IN (SELECT "f"."Id", "f"."CreatedAt"
    FROM "Foo" AS "f"
    WHERE "f"."CreatedAt" <= CURRENT_TIMESTAMP);
Run Code Online (Sandbox Code Playgroud)

它删除当前时间之前创建的记录。

这给出了相同的结果:

DELETE FROM "Foo"
WHERE "Foo"."CreatedAt"
IN (SELECT "f"."CreatedAt"
    FROM "Foo" AS "f"
    WHERE "f"."CreatedAt" <= CURRENT_TIMESTAMP);
Run Code Online (Sandbox Code Playgroud)

我不知道为什么Foo.Id将 包含在WHERE子句中 - 也许是各种重构留下的垃圾(例如,它可能已用于批量删除ORDER BY "f"."Id" LIMIT 1000)。但因为这是一场PK,我不愿意删除它,因为也许它的存在是有原因的。

是否有理论/性能原因将其放在那里,或者这两个查询是否等效?

(这同时针对 postgres 和 sqlite。)

postgresql sqlite query subquery relational-theory

6
推荐指数
1
解决办法
773
查看次数