在mysql中相交或减少

时间:2013-10-27 07:56:43

标签: mysql sql

我有以下查询,

SELECT DISTINCT (U.uid)
FROM users U
    ,friends F
WHERE U.STATUS = '1'
    AND U.uid = F.friend_two
    AND F.friend_one = '1'
    AND F.ROLE = 'fri'

以上查询返回32行。

SELECT DISTINCT (U.uid)
FROM users U
    ,friends F
WHERE U.STATUS = '1'
    AND U.uid = F.friend_one
    AND F.friend_two = '1'
    AND F.ROLE = 'fri'

以上查询返回15行。

我需要结合并取相交的结果。相交的行是14行(表示两个表中的相同U.uid是14行)

4 个答案:

答案 0 :(得分:1)

试试这个:

SELECT *
FROM (
    SELECT DISTINCT (U.uid) UID
    FROM users U
        ,friends F
    WHERE U.STATUS = '1'
        AND U.uid = F.friend_two
        AND F.friend_one = '1'
        AND F.ROLE = 'fri'
    ) A
INNER JOIN (
    SELECT DISTINCT (U.uid) UID
    FROM users U
        ,friends F
    WHERE U.STATUS = '1'
        AND U.uid = F.friend_one
        AND F.friend_two = '1'
        AND F.ROLE = 'fri'
    ) B ON A.UID = B.UID

这基本上是您指定的两个查询的两个结果集的用户ID的交集。

答案 1 :(得分:1)

获取交集的最直接方法是加入查询:

SELECT uid FROM (
  SELECT DISTINCT U.uid
  FROM   users U JOIN friends F ON F.friend_two=U.uid AND F.friend_one = '1'
  WHERE  U.status='1' AND F.role='fri'
) NATURAL JOIN (
  SELECT DISTINCT U.uid
  FROM   users U JOIN friends F ON F.friend_one=U.uid AND F.friend_two = '1'
  WHERE  U.status='1' AND F.role='fri'
)

但是,您也可以组合查询并过滤分组结果:

SELECT   U.uid
FROM     users U JOIN friends F ON (
           F.friend_one = U.uid AND F.friend_two = '1'
         ) OR (
           F.friend_two = U.uid AND F.friend_one = '1'
         )
WHERE    U.status='1' AND F.role='fri'
GROUP BY U.uid
HAVING   SUM(F.friend_one = U.uid AND F.friend_two = '1')
     AND SUM(F.friend_two = U.uid AND F.friend_one = '1')

答案 2 :(得分:1)

如果您使用EXISTS而不是联接重写2个查询,则可以先删除DISTINCT(我认为uidUsers的主键这里)第二,INTERSECTEXCEPT(也称为MINUS)操作是明确的:

查询1:

SELECT U.uid
FROM users U
WHERE U.status = '1'
  AND EXISTS
      ( SELECT *
        FROM friends F
         WHERE U.uid = F.friend_two
           AND F.friend_one = '1'
           AND F.ROLE = 'fri'
      ) ;

查询2:

SELECT U.uid
FROM users U
WHERE U.status = '1'
  AND EXISTS
      ( SELECT *
        FROM friends F
         WHERE U.uid = F.friend_one
           AND F.friend_two = '1'
           AND F.ROLE = 'fri'
      ) ;

查询3:INTERSECT

SELECT U.uid
FROM users U
WHERE U.status = '1'
  AND EXISTS
      ( SELECT *
        FROM friends F
         WHERE U.uid = F.friend_two
           AND F.friend_one = '1'
           AND F.ROLE = 'fri'
      )
  AND EXISTS
      ( SELECT *
        FROM friends F
         WHERE U.uid = F.friend_one
           AND F.friend_two = '1'
           AND F.ROLE = 'fri'
      ) ;

查询4:EXCEPTMINUS

SELECT U.uid
FROM users U
WHERE U.status = '1'
  AND EXISTS
      ( SELECT *
        FROM friends F
         WHERE U.uid = F.friend_two
           AND F.friend_one = '1'
           AND F.ROLE = 'fri'
      )
  AND NOT EXISTS                       -- notice the NOT here
      ( SELECT *
        FROM friends F
         WHERE U.uid = F.friend_one
           AND F.friend_two = '1'
           AND F.ROLE = 'fri'
      ) ;

答案 3 :(得分:1)

另外两个版本值得尝试。
第一个是使用半连接,第二个是将friends表连接到自身。

SELECT distinct(U.uid) 
FROM users U
JOIN friends F  ON U.uid=F.friend_two AND F.friend_one='1'
WHERE U.status='1' AND F.role='fri' 
    AND EXISTS(
      SELECT 1 FROM friends F1
      WHERE U.uid=F1.friend_one 
        AND F1.friend_two='1'
        AND F1.role = 'fri'
    )
;

SELECT distinct(U.uid) 
FROM users U
JOIN friends F  ON U.uid=F.friend_two AND F.friend_one='1'
JOIN friends F1 ON U.uid=F1.friend_one AND F1.friend_two='1'
WHERE U.status='1' AND F.role='fri' AND F1.role = 'fri'