【问题标题】:Select multiple rows with duplicates limited to unique meta rows MySQL选择多行,重复项仅限于唯一元行 MySQL
【发布时间】:2014-10-14 21:59:53
【问题描述】:

我需要对 MySQL 数据库进行一个非常具体的查询,我将从表示例开始:

+----+---------------+------------------------------------+----------+
| id | data          | pattern_key                        | hash     |
+----+---------------+------------------------------------+----------+
|  1 | {"user":true} | NOTIFICATIONHUB::SYSTEM            | ABCDEFGH |
|  2 | {"user":true} | NOTIFICATIONHUB::SYSTEM            | ABCDEFGH |
|  3 | {"user":true} | NOTIFICATIONHUB::SYSTEM            | ABCDEFGH |
|  4 | {"user":true} | NOTIFICATIONHUB::SYSTEM            | HGFEDCBA |
|  5 | {"user":true} | NOTIFICATIONHUB::SYSTEM            | HGFEDCBA |
|  6 | {"user":true} | NOTIFICATIONHUB::SYSTEM            | OPQRSTUW |
|  7 | {"user":true} | NOTIFICATIONHUB::SYSTEM            | ABCDEFGH |
|  8 | {"user":true} | NOTIFICATIONHUB::SYSTEM            | ABCDEFGH |
|  9 | {"user":true} | NOTIFICATIONHUB::SYSTEM            | IJKLMNOP |
| 10 | {"user":true} | NOTIFICATIONHUB::SYSTEM            | ABCDEFGH |
+----+---------------+------------------------------------+----------+

如您所见,我有列 data 和 pattern_key,此时它们无关紧要。重要的是哈希列,它允许相同的值,即:ABCDEFGH。我想要做的是选择按 ID 降序排列的 5 行,但包括哈希列上的重复项,并且仅当它们彼此之后。该表的查询结果应该是:

+----+---------------+------------------------------------+----------+
| id | data          | pattern_key                        | hash     |
+----+---------------+------------------------------------+----------+
| 10 | {"user":true} | NOTIFICATIONHUB::SYSTEM            | ABCDEFGH |
|  9 | {"user":true} | NOTIFICATIONHUB::SYSTEM            | IJKLMNOP |
|  8 | {"user":true} | NOTIFICATIONHUB::SYSTEM            | ABCDEFGH |
|  7 | {"user":true} | NOTIFICATIONHUB::SYSTEM            | ABCDEFGH |
|  6 | {"user":true} | NOTIFICATIONHUB::SYSTEM            | OPQRSTUW |
|  5 | {"user":true} | NOTIFICATIONHUB::SYSTEM            | HGFEDCBA |
+----+---------------+------------------------------------+----------+

我们有 6 条记录,不是限制为 5 条,但包含第 7 行,因为第 8 行具有相同的哈希值。这种行为必须忽略重复的数量,只要它们一个接一个,所以如果我们按 id 升序排序,我们会得到:

+----+---------------+------------------------------------+----------+
| id | data          | pattern_key                        | hash     |
+----+---------------+------------------------------------+----------+
|  1 | {"user":true} | NOTIFICATIONHUB::SYSTEM            | ABCDEFGH |
|  2 | {"user":true} | NOTIFICATIONHUB::SYSTEM            | ABCDEFGH |
|  3 | {"user":true} | NOTIFICATIONHUB::SYSTEM            | ABCDEFGH |
|  4 | {"user":true} | NOTIFICATIONHUB::SYSTEM            | HGFEDCBA |
|  5 | {"user":true} | NOTIFICATIONHUB::SYSTEM            | HGFEDCBA |
|  6 | {"user":true} | NOTIFICATIONHUB::SYSTEM            | OPQRSTUW |
|  7 | {"user":true} | NOTIFICATIONHUB::SYSTEM            | ABCDEFGH |
|  8 | {"user":true} | NOTIFICATIONHUB::SYSTEM            | ABCDEFGH |
|  9 | {"user":true} | NOTIFICATIONHUB::SYSTEM            | IJKLMNOP |
+----+---------------+------------------------------------+----------+

因为我们有 3 个 ABCDEFGH(我认为是 1 个唯一的元行)、2 个 HGFEDCBA(2 个唯一的元行)、1 个 OPQRSTUW(第 3 个唯一的行)、2 个 ABCDEFGH(4 个唯一的元行,因为它们是从前 3 个 ABCDEFGH 与其他哈希)和一个 IJKLMNOP。

我在考虑 group by,但它会裁剪重复项,我希望将它们包含在数据集中。有什么想法吗?

感谢@Uueerdo,我想出了那个解决方案(是的,无论如何都需要加入):

SET @i := 0;
SET @lastHash := '';
SELECT *
FROM
  (SELECT notification_real_id AS id, data, pattern_key, @i := IF(hash <> @lastHash, @i + 1, @i) AS hashGroup, @lastHash := hash AS hash
   FROM
     ( SELECT notifications.id AS notification_real_id,
              data,
              pattern_key,
              hash
      FROM notifications
      INNER JOIN notifications_users ON notifications.id = notifications_users.notification_id
      WHERE notifications_users.user_id = 1) AS subJoin
   ORDER BY notification_real_id DESC) AS subQ
WHERE hashGroup <= 5;

【问题讨论】:

  • 那么,换个说法,你想LIMIT 查询结果的unique 散列数吗?例如,您最多需要 5 个不同的哈希值,但可能是 5 行,也可能是 8 行……对吗?
  • 是的!我想选择 UNTIL 5 个不同的散列,但问题是它们可以重复(所以不是真正不同),只要它们与先前的“相同散列”组与另一行和另一个散列分开。
  • 存储过程就足够了吗?
  • 如果这是mysql,你可以按hash分组,按id desc排序并选择max(id),然后限制5。mysql没有与mssql相同的检查,这不会与合作
  • 我不想使用存储过程,因为它是 CMS 系统插件的一部分,我不想处理存储过程的添加和删除。

标签: mysql


【解决方案1】:

我没有时间验证它是否完全正确,但这样的事情应该可以工作:

SET @i := 0;
SET @lastHash := '';
SELECT * 
FROM (
  SELECT id, data, pattern_key
   , @i := IF(hash <> @lastHash, @i + 1, @i) AS hashGroup
   , @lastHash := hash
  FROM table
  ORDER BY id DESC
) AS subQ
WHERE hashGroup <= 5
;

或者(不需要变量)(不推荐:如果没有数据黑客,可靠性不高,连接不灵活,而且很可能慢得多)

SELECT * 
FROM the_table  
WHERE id > (
   SELECT MAX(id) AS lastID    
   FROM the_table
   GROUP BY hash 
   ORDER BY lastID DESC LIMIT 5, 1
  )
;

【讨论】:

  • @Egregore 你试过了吗?
  • 这实际上工作得很好,我已经找到了使用存储过程的方法,所以我接受了这个答案。感谢大家的帮助!
  • 我不认为这需要在 SP 中
  • 我希望使用一个查询来执行此操作,并且不会使用存储过程污染 CMS 数据库,我也不想使用变量,但我想不出如何在任何其他情况下执行此操作方式。
  • 我可以制作一个不使用变量的,但它会相当可怕。这种事情:SELECT blah FROM blah_table WHERE blah_id > (SELECT MIN(lastID) FROM (SELECT a_field, MAX(ID) AS lastID FROM blah_table GROUP BY a_field ORDER BY lastID DESC LIMIT 6));
猜你喜欢
  • 2021-10-30
  • 1970-01-01
  • 2012-12-06
  • 1970-01-01
  • 2011-12-17
  • 1970-01-01
  • 2016-12-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多