【问题标题】:MySQL LIMIT statement, wrong number of rows are returnedMySQL LIMIT 语句,返回错误的行数
【发布时间】:2019-12-21 00:59:44
【问题描述】:

我有相当复杂的查询(使用 MySQL 8.0.11)

SELECT
  x.id,
  x.text,
  x.campaign_id,
  x.ad_group_id,
  x.close_variant,
  x.keywords,
  x.terms,
  x.impressions,
  x.clicks,
  x.conversion_value,
  x.avg_position,
  x.conversions,
  x.cost,
  x.campaigns,
  x.ad_groups,
  EXISTS (
    SELECT
        *
    FROM
        reports_biddablekeyword cbk
        JOIN reports_keyword ck ON (cbk.keyword_id = ck.id)
    wHERE
        cbk.customer_id = 3512658134 AND
        cbk.campaign_id = x.campaign_id AND
        cbk.ad_group_id = x.ad_group_id AND
        phrase_conflict(x.text, ck.text, ck.match_type)
) AS conflict,

    EXISTS (
        SELECT
            *
        FROM
            reports_negativekeyword bnk
            JOIN reports_keyword bk ON (bnk.keyword_id = bk.id)
        wHERE
            bnk.customer_id = 3512658134 AND
            bnk.campaign_id = x.campaign_id AND
            bnk.ad_group_id = x.ad_group_id AND
            bk.match_type = 'PHRASE' AND
            phrase_match(x.text, bk.text, bk.match_type)
    )
 AS blocked,
  ROUND(x.clicks / x.impressions * 100, 1) AS ctr,
  ROUND(x.cost / x.conversions, 2) AS cpa,
  ROUND(x.cost / x.clicks, 2) AS cpc,
  ROUND(x.conversion_value / x.cost, 2) AS roi
FROM
(
  SELECT
    p.id AS id,
    p.text AS text,
    r.campaign_id AS campaign_id,
    r.ad_group_id AS ad_group_id,
    IF(SUM(r.match_type_close_variant) = COUNT(*), "only", IF(SUM(r.match_type_close_variant) > 0, "some", "none")) AS close_variant,
    COUNT(DISTINCT r.keyword_id) AS keywords,
    COUNT(DISTINCT r.term) AS terms,
    IFNULL(SUM(r.impressions), 0) AS impressions,
    IFNULL(SUM(r.clicks), 0) AS clicks,
    SUM(r.conversion_value) AS conversion_value,
    ROUND(SUM(r.avg_position * r.impressions) / SUM(r.impressions), 2) AS avg_position,
    ROUND(IFNULL(SUM(r.conversions), 0), 2) AS conversions,
    ROUND(IFNULL(SUM(r.cost), 0), 2) AS cost,
    COUNT(DISTINCT r.campaign_id) AS campaigns,
    COUNT(DISTINCT r.ad_group_id) AS ad_groups
  FROM
    reports_row r
    JOIN reports_phraserow pr ON (r.id = pr.row_id)
    JOIN reports_phrase p ON (p.id = pr.phrase_id)
  WHERE
    (r.customer_id) = 3512658134 AND
    (p.text != p.common_term) = 0
  GROUP BY
    r.campaign_id,
    r.ad_group_id,
    pr.phrase_id
  HAVING
    conversions = 0 AND
    cost > 43.97137500000000091533811780
  ) AS x
HAVING
  conflict = 0 AND
  blocked = 0
ORDER BY
  cost DESC

按原样运行查询,我得到 173 行结果。

在 ORDER BY 之后添加 LIMIT 我得到了奇怪的记录数

  • ... LIMIT 1 - 0 行返回
  • ... LIMIT 10 - 返回 0 行
  • ... LIMIT 16 - 返回 1 行(返回任何行的最低限制)
  • ... LIMIT 100 - 27 行返回
  • ... LIMIT 297 - 172 行返回
  • ... LIMIT 298 - 返回 172 行(返回与无限制查询相同的行的最低限制)

我不知道出了什么问题。

更新:我意识到将所有内容包装到 SELECT xxx.* FROM (...) AS xxx LIMIT N 会返回正确的结果。但我仍然很好奇为什么需要这样做。

UPDATE2:也用常量值替换存在的子查询使限制正常工作

【问题讨论】:

  • 如果在外部SELECT 中使用WHERE 而不是HAVING 会发生什么? HAVING 通常与 GROUP BY 结合使用,而您没有。

标签: mysql sql sql-limit


【解决方案1】:

您有一个没有GROUP BY 的聚合查询。

您应该遇到语法错误,但您明显覆盖了 MySQL 8 的默认设置。

未聚合的列来自任意行。这些值可以随运行而变化。

远非神秘,您不一致的结果是为什么 ONLY_FULL_GROUP_BY 现在是默认设置以及为什么几乎所有其他数据库都遵循 SQL 标准不允许像您这样的查询。

【讨论】:

  • 查询滥用mysql默认行为并将非聚合文件(文本,id)放入结果中是真的,因为组的所有值都是相等的。仍然是个谜,即使启用了 ONLY_FULL_GROUP_BY,我的查询也不会产生错误。 (尝试了明显无效的查询,它确实如此)。其次,即使我将 text 和 id 放入 group id 它仍然不会改变限制行为
  • @farincz 。 . .你错过了重点。这不是limit 的行为。这是having 的行为。问题是哪些行被过滤掉了。每次运行都是不确定的。有时查询返回的那一行被过滤掉了;有时不会。
  • 我不明白这与 group by 有什么关系。经过查询实验后,我发现如果查询不包含 EXISTS 子查询或 HAVING 在此列上的条件,则限制是可以的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-12
相关资源
最近更新 更多