MySQL UNION,Order By和IN Statement All In One Query

时间:2012-12-24 05:28:47

标签: mysql database search

好的,所以我正在研究一个MySQL的搜索功能但是遇到了一些我似乎无法解决的问题。我正在尝试制作一个脚本来搜索用户朋友,并返回得分更高的朋友。这就是我到目前为止所做的:

SELECT id, first_name, last_name, image_id FROM users
WHERE id IN (
    SELECT receiver AS friend FROM friends WHERE initiator = :me AND status = :status        
     UNION
    SELECT initiator AS friend FROM friends WHERE receiver = :me AND status = :status
) ORDER BY score AND concat(first_name, ' ', last_name) LIKE '%test query%';

现在一切正常,直到我尝试按分数订购朋友。任何人都可以锻炼如何按分数订购朋友吗?如果你需要我澄清什么,只要问。

我有以下两张表。

用户表enter image description here

朋友表: enter image description here

根据要求,这里有一些示例数据:

例如,我有三个用户:

ID: 1, first_name: Michael, last_name: Sample
ID: 2, first_name: John, last_name: Citizen
ID: 3, first_name: Caitlin, last_name: Wired

下面的第一个条目将让迈克尔和凯特琳成为朋友,表明迈克尔发起了一个朋友请求而凯特琳(接收者)接受了它。 (因此1)的状态他们的基本分数是10.第二个条目显示John也是Caitlin的朋友(由Caitlin发起)但得分更高。

ID: 10000, initiator: 1, receiver: 3, status: 1, score: 10
ID: 10001, initiator: 3, receiver: 2, status: 1, score: 20

所以在这个样本数据的情况下。如果Caitlin是用户搜索她的朋友,它应该显示John而不是Michael。

2 个答案:

答案 0 :(得分:3)

外部语句仅从users列中选择,该列没有score列。几乎所有使用子选择的语句都可以(并且应该)使用连接重写。在这种特殊情况下,它将允许在子句中使用所有friends字段。

SELECT u.id, u.first_name, u.last_name, u.image_id 
  FROM users AS u
    JOIN friends AS f 
      ON ...

子选择的WHERE子句中使用的表达式成为连接条件。联盟在某种意义上等同于OR(两者基本上都是conjunctions)。

      ON    (u.id = f.receiver AND f.initiator=:me AND status=:status)
         OR (u.id = f.initiator AND f.receiver=:me AND status=:status)

声明的其余部分几乎保持不变。

  WHERE concat(first_name, ' ', last_name) LIKE '%test query%'
  ORDER BY score
;

总之,那是:

SELECT u.id, u.first_name, u.last_name, u.image_id 
  FROM users AS u
    JOIN friends AS f 
      ON    (u.id = f.receiver AND f.initiator=:me AND status=:status)
         OR (u.id = f.initiator AND f.receiver=:me AND status=:status)
  WHERE concat(first_name, ' ', last_name) LIKE '%test query%'
  ORDER BY score
;

请注意,这是未经测试的,只是在我的头顶。

答案 1 :(得分:0)

  • 你没有选择分数
  • 联合查询在外部查询中排序

例如,使用union

订购
SELECT T.* /*ANY COLUMN SET WITH(OUT) SCORE */ FROM(
 SELECT SCORE,.... FROM ANOTHERTABLE  WHERE .....
 UNION SELECT SCORE,.... FROM ANOTHERTABLE WHERE ...

) T
ORDER BY SCORE

更好的重写

SELECT id, first_name, last_name, image_id FROM users
JOIN (
SELECT score,receiver AS friend FROM friends WHERE initiator = :me AND status = :status        
 UNION
SELECT score,initiator AS friend FROM friends WHERE receiver = :me AND status = :status
) t ON T.ID = users.id ORDER BY score AND concat(first_name, ' ', last_name) LIKE '%test query%';