【问题标题】:How to apply the MINUS efficiently on mysql query for tables with large data如何在具有大数据的表的 mysql 查询中有效地应用 MINUS
【发布时间】:2011-08-02 18:40:19
【问题描述】:

我有 2 个如下表 -

CREATE TABLE IF NOT EXISTS `nl_members` (
  `member_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `member_email` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `member_confirmation_code` varchar(35) COLLATE utf8_unicode_ci NOT NULL,
  `member_enabled` enum('Yes','No') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'Yes',
  PRIMARY KEY (`member_id`),
  UNIQUE KEY `TUC_nl_members_1` (`member_email`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=58520 ;

CREATE TABLE IF NOT EXISTS `nl_member_group_xref` (
  `group_id` int(10) unsigned NOT NULL,
  `member_id` int(10) unsigned NOT NULL,
  `member_subscribed` enum('Yes','No') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'Yes',
  `subscribe_date` int(10) unsigned NOT NULL DEFAULT '0',
  `unsubscribe_date` int(10) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`group_id`,`member_id`),
  KEY `nl_members_nl_member_group_xref` (`member_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;


ALTER TABLE `nl_member_group_xref`
 ADD CONSTRAINT `nl_members_nl_member_group_xref` FOREIGN KEY (`member_id`) REFERENCES `nl_members` (`member_id`),
 ADD CONSTRAINT `nl_member_groups_nl_member_group_xref` FOREIGN KEY (`group_id`) REFERENCES `nl_member_groups` (`group_id`);

两者都有关于数百万的大量数据。

我想要的是高效地将 MINUS 应用于结果集。

例如,

我想获取 ID 为 1 的 Group1 中的所有用户,减去 ID 为 2 的 Group2 和 ID 为 3 的 Group3 中的所有用户

我怎样才能有效地做到这一点?尽可能快地运行查询。

更新

我想要的是这样的——

在成员表“nl_members”中,我保留了所有成员的列表,这些成员可能与一个或多个组相关联。

对于成员的每个组关联,“nl_member_group_xref”表中都会有一行。

因此,如果一个成员与 3 个组相关联,则 member_group_xref 表中将有 3 个条目。

现在我想要的是让所有成员都包含在第 1 组中,但如果他们也属于第 2 组和第 3 组,则排除他们。

希望这会有所帮助。

【问题讨论】:

  • 您有现有的查询吗?如果您说要将 group2 和 3 中的所有用户减去 1,我认为这是数字结果。但是您说所有用户,那么这意味着每个用户的数据。所以我对你的问题的理解是 LIMIT = 0,(G1 - (G2 + G3)) 其中限制将包括在你的查询结束时。如果我的理解有误,您介意再解释一下吗?

标签: mysql query-optimization large-data


【解决方案1】:

对于您更新的问题,您将需要加入两个表并将其与 members_id 分组:请参阅下面的查询是否会显示您正在寻找的结果。

更新:

  SELECT 
         nm.*, nmgx.*
    FROM nl_members nm
   INNER JOIN nl_member_group_xref nmgx
      ON nm.member_id = nmgx.member_id
    LEFT JOIN (SELECT 
                      nmgx2.member_id
                 FROM nl_member_group_xref nmgx2
                WHERE nmgx2.group_id <> 1) nmgx22
      ON nmgx22.member_id = nm.member_id
   WHERE nmgx22.member_id IS NULL
   GROUP BY nm.member_id;

注意:我使用 * 来获取所有字段名称。您获得特定字段,因此查询会更快,因为它只会获得更少的结果。前任。 member_id 像 nm.member_id

如果这不是您要查找的内容,请通知我,然后我会尽可能准确地更新此查询

【讨论】:

  • 我已经检查了代码并且它正在工作,但是您仍然需要根据您的结果进行检查,它可能与您真正想要的有所不同。现在就试试吧。
  • 感谢您的回复。但这不是我要找的。它是简单的内部连接,但需要找到 group1 的成员减去 group2 和 group3 中的所有成员
  • @anjan,我更新了我的帖子,看看。我希望这是您正在寻找的,关于优化我不确定这是否比您当前的工作查询更快。
  • thnx :) 我会试一试并告诉你
【解决方案2】:

您是否尝试过使用MINUS 运算符?

【讨论】:

  • 对于非常大的数据集,MINUS 将花费双倍的时间,因为它必须获取两个结果集然后消除重复项
  • OP 询问的是减去集合而不是数字。从这个意义上说,MySQL 没有 EXCEPT / MINUS 运算符。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-08
  • 2013-11-29
  • 2011-11-22
  • 2018-08-26
  • 2018-05-14
  • 1970-01-01
相关资源
最近更新 更多