将限制结果加入连接表而不进行子选择

时间:2014-10-04 17:24:53

标签: mysql sql join left-join

我有一个查询连接到表(用户和朋友用户),我想将第二个连接表限制为组的前n行。 我在堆栈上阅读了几个线程和本文: http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/

我在想:是否有任何改变不使用子选择

这是一个数据集示例:

+----+------------+------------+------------+----------+-----------------+---------------------+----------+-------------------+------+
| id | created_at | updated_at | deleted_at | status   | username        | mail                | password | recovery_password | pin  |
+----+------------+------------+------------+----------+-----------------+---------------------+----------+-------------------+------+
|  1 | 1412441692 |       NULL |       NULL | enabled  | first.first     | first@first.com     | 111111   | NULL              | 1111 |
|  2 | 1412441692 |       NULL |       NULL | enabled  | second.second   | second@second.com   | 222222   | NULL              | 2222 |
|  3 | 1412441692 |       NULL |       NULL | disabled | third.third     | third@third.com     | 333333   | NULL              | 3333 |
|  4 | 1412441692 |       NULL |       NULL | enabled  | fourth.fourth   | fourth@fourth.com   | 444444   | NULL              | 4444 |
|  5 | 1412441692 |       NULL |       NULL | disabled | fifth.fifth     | fifth@fifth.com     | 555555   | NULL              | 5555 |
|  6 | 1412441692 |       NULL |       NULL | enabled  | sixth.sixth     | sixth@sixth.com     | 666666   | NULL              | 6666 |
|  7 | 1412441692 |       NULL |       NULL | disabled | seventh.seventh | seventh@seventh.com | 777777   | NULL              | 7777 |
+----+------------+------------+------------+----------+-----------------+---------------------+----------+-------------------+------+

+-----+--------+---------+-----+--------+------------+-----------+
| id1 | otype1 | atype   | id2 | otype2 | pushed_at  | popped_at |
+-----+--------+---------+-----+--------+------------+-----------+
|   1 | user   | friends |   2 | user   | 1412441692 |      NULL |
|   1 | user   | friends |   3 | user   | 1412441692 |      NULL |
|   2 | user   | friends |   1 | user   | 1412441692 |      NULL |
|   2 | user   | friends |   6 | user   | 1412441692 |      NULL |
|   4 | user   | friends |   3 | user   | 1412441692 |      NULL |
|   6 | user   | friends |   2 | user   | 1412441692 |      NULL |
|   6 | user   | friends |   7 | user   | 1412441692 |      NULL |
+-----+--------+---------+-----+--------+------------+-----------+

以下是我现在正在使用的查询。

SELECT `t1`.`id` AS `id1`, t2.* FROM `User` AS `t1`, `user` AS `t2`, `association` AS `a` WHERE ( t1.id = a.id1 ) AND ( t2.id = a.id2 ) AND ( a.otype1 = "user" ) AND ( a.otype2 = "user") AND ( a.atype = "friends" )

+-----+----+------------+------------+------------+----------+-----------------+---------------------+----------+-------------------+------+
| id1 | id | created_at | updated_at | deleted_at | status   | username        | mail                | password | recovery_password | pin  |
+-----+----+------------+------------+------------+----------+-----------------+---------------------+----------+-------------------+------+
|   1 |  2 | 1412441692 |       NULL |       NULL | enabled  | second.second   | second@second.com   | 222222   | NULL              | 2222 |
|   1 |  3 | 1412441692 |       NULL |       NULL | disabled | third.third     | third@third.com     | 333333   | NULL              | 3333 |
|   2 |  1 | 1412441692 |       NULL |       NULL | enabled  | first.first     | first@first.com     | 111111   | NULL              | 1111 |
|   2 |  6 | 1412441692 |       NULL |       NULL | enabled  | sixth.sixth     | sixth@sixth.com     | 666666   | NULL              | 6666 |
|   4 |  3 | 1412441692 |       NULL |       NULL | disabled | third.third     | third@third.com     | 333333   | NULL              | 3333 |
|   6 |  2 | 1412441692 |       NULL |       NULL | enabled  | second.second   | second@second.com   | 222222   | NULL              | 2222 |
|   6 |  7 | 1412441692 |       NULL |       NULL | disabled | seventh.seventh | seventh@seventh.com | 777777   | NULL              | 7777 |
+-----+----+------------+------------+------------+----------+-----------------+---------------------+----------+-------------------+------+

但我想得到:

+-----+----+------------+------------+------------+----------+-----------------+---------------------+----------+-------------------+------+
| id1 | id | created_at | updated_at | deleted_at | status   | username        | mail                | password | recovery_password | pin  |
+-----+----+------------+------------+------------+----------+-----------------+---------------------+----------+-------------------+------+
|   1 |  2 | 1412441692 |       NULL |       NULL | enabled  | second.second   | second@second.com   | 222222   | NULL              | 2222 |
|   2 |  1 | 1412441692 |       NULL |       NULL | enabled  | first.first     | first@first.com     | 111111   | NULL              | 1111 |
|   4 |  3 | 1412441692 |       NULL |       NULL | disabled | third.third     | third@third.com     | 333333   | NULL              | 3333 |
|   6 |  2 | 1412441692 |       NULL |       NULL | enabled  | second.second   | second@second.com   | 222222   | NULL              | 2222 |
+-----+----+------------+------------+------------+----------+-----------------+---------------------+----------+-------------------+------+

1 个答案:

答案 0 :(得分:1)

是的,您可以使用变量。首先,您应该更像这样编写查询:

SELECT u1.id AS id1, u2.*
FROM association a JOIN
     User u1
     on u1.id = a.id1 and a.otype1 = 'user' JOIN
     `user` u2
     ON u2.id = a.id2 and a.otype2 = 'user'
WHERE a.atype = 'friends'

注意使用(1)显式join语法; (2)字符串常量的单引号; (3)作为表名缩写的别名; (4)最少使用反引号(只会使查询难以阅读。

SELECT uu.*
FROM (SELECT u1.id AS id1, u2.*,
             (@rn := if(@id1 = id1, @rn + 1,
                        if(@id1 := id1, 1, 1)
                       )
             ) rn
      FROM association a JOIN
           User u1
           on u1.id = a.id1 and a.otype1 = 'user' JOIN
           `user` u2
           ON u2.id = a.id2 and a.otype2 = 'user' CROSS JOIN
           (SELECT @id1 := 0, @rn := 0) vars
      WHERE a.atype = 'friends'
      ORDER BY u1.id
     ) uu
WHERE rn = 1;