【问题标题】:Quicker way to get this data out of mySQL从 mySQL 中获取这些数据的更快方法
【发布时间】:2021-03-06 09:41:44
【问题描述】:

我目前这样做是为了从我们的表中获取一些数据:

SELECT DISTINCT(CategoryID),Distance FROM glinks_DistancesForTowns WHERE LinkID = $linkID ORDER BY Distance LIMIT 20

我正在为我们拥有的每个链接 ID(50k 奇数)进行迭代。我在 Perl 中处理它们:

my @cats;
while (my ($catid,$distance) = $sth->fetchrow) {
    push @cats, $cat;
}

我正在尝试查看是否有更好的方法在使用 MySQL 的子查询中执行此操作,而不是执行 50k 较小的查询(即每个链接一个)

表的基本结构是:

glinks_Links
    ID
glinks_DistancesForTowns 
    LinkID
    CategoryID
    Distance

我确信一定有一个简单的方法来做到这一点 - 但我只是没有看到它。

根据要求 - 这是表结构的转储。它实际上比这更复杂,但其他字段只保存值,所以我把这些位去掉,以便更清楚地了解结构:

CREATE TABLE `glinks_DistancesForTowns` (
 `LinkID` int(11) DEFAULT NULL,
 `CategoryID` int(11) DEFAULT NULL,
 `Distance` float DEFAULT NULL,
 `isPaid` int(11) DEFAULT NULL,
 KEY `LinkID` (`LinkID`),
 KEY `CategoryID` (`CategoryID`,`isPaid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1


CREATE TABLE `glinks_Links` (
 `ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
 `Title` varchar(100) NOT NULL DEFAULT '',
 `URL` varchar(255) NOT NULL DEFAULT 'http://',
 PRIMARY KEY (`ID`),
 KEY `booking_hotel_id_fk` (`booking_hotel_id_fk`)
) ENGINE=MyISAM AUTO_INCREMENT=617547 DEFAULT CHARSET=latin1

这是我所希望的:

SELECT glinks_Links.ID FROM glinks_Links as links, glinks_DistancesForTowns as distance (
        SELECT DISTINCT(CategoryID),Distance FROM distance WHERE distance.LinkID = links.ID ORDER BY Distance LIMIT 20
    )

但显然那是行不通的;)

【问题讨论】:

  • 您的查询有误。 PS。 DISTINCT 不是函数。
  • ? DISTINCT(xxx) 在 mySQL 中很好。
  • 是的。但它执行的不是你想的动作。 xxx 已计算。 (xxx) 是一个表达式,其值为xxx,则形成一个输出行ROW(xxx, yyy)。形成所有行后,将 DISTINCT 应​​用于行集(完全重复的整行被折叠)。
  • DISTINCT(CategoryID) - CategoryID 是列名,所以它出售它所做的只是获取该匹配项的不同类别 ID。这部分查询工作正常。我的主要问题是如何将它加入一个班轮:)
  • 所以它的全部卖点就是为那场比赛获取不同的类别 ID 再读一遍我的 cmets。想想他们。以前 - 假设您当前对 DISTINCT 的了解不正确。

标签: mysql query-optimization greatest-n-per-group


【解决方案1】:

听起来您想要每个链接的距离排名前 20 的城镇,对吧?

MySQL 8.0 支持窗口函数,这将是编写查询的方式:

WITH cte AS (
  SELECT l.ID, ROW_NUMBER() OVER(PARTITION BY l.ID ORDER BY d.Distance) AS rownum
  FROM glinks_Links as l
  JOIN glinks_DistancesForTowns AS d ON d.LinkID = l.ID
) SELECT ID FROM cte WHERE rownum <= 20;

早于 8.0 的版本不支持 SQL 的这些功能,因此您必须使用用户定义的变量或自联接来发挥创意。例如,请参阅我对How to SELECT the newest four items per category?的回答

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多