2013-07-16 36 views
1

我有一個查詢應該檢索用戶的朋友。MYSQL查詢檢索友誼只有一種方式?

鑑於我們的情況是user two而我們sentuser one的請求,查詢應返回user one的帳戶信息。 (SQLfiddle of this scenario)正常工作]

鑑於我們user one的情況,我們從recieveduser two請求查詢應返回的帳戶信息user two。 (SQLfiddle of this scenario)[返回空結果]

所以查詢工作正常,只要我們發送請求的用戶,但是如果我們接受這是行不通的請求的用戶。

我可以通過切換JOINs,LEFT => RIGHTRIGHT => LEFT來解決這個問題。但是這打破了第一種情況。
我可以修復我做兩個查詢的聯合。 (SQLfiddle of this scenario),但肯定不是這樣做的最有效的方法。所以,基本問題:我應該如何創建這個查詢?

場景一:

SELECT `accounts`.*, 
    IFNULL(`f1`.`sender`,  `f2`.`sender`)  AS `sender`, 
    IFNULL(`f1`.`recipient`,  `f2`.`recipient`)  AS `recipient`, 
    IFNULL(`f1`.`date_sent`,  `f2`.`date_sent`)  AS `date_sent`, 
    IFNULL(`f1`.`date_reviewed`, `f2`.`date_reviewed`) AS `date_reviewed`, 
    IFNULL(`f1`.`accepted`,  `f2`.`accepted`)  AS `accepted` 
FROM `accounts` 
    LEFT JOIN `friendships` AS `f1` ON `accounts`.`id` = `f1`.`sender` 
    RIGHT JOIN `friendships` AS `f2` ON `accounts`.`id` = `f2`.`recipient` 
WHERE (`f1`.`recipient` = 2 OR `f2`.`sender` = 2); 

分區拼接方案二

SELECT `accounts`.*, 
    IFNULL(`f1`.`sender`,  `f2`.`sender`)  AS `sender`, 
    IFNULL(`f1`.`recipient`,  `f2`.`recipient`)  AS `recipient`, 
    IFNULL(`f1`.`date_sent`,  `f2`.`date_sent`)  AS `date_sent`, 
    IFNULL(`f1`.`date_reviewed`, `f2`.`date_reviewed`) AS `date_reviewed`, 
    IFNULL(`f1`.`accepted`,  `f2`.`accepted`)  AS `accepted` 
FROM `accounts` 
    RIGHT JOIN `friendships` AS `f1` ON `accounts`.`id` = `f1`.`sender` 
    LEFT JOIN `friendships` AS `f2` ON `accounts`.`id` = `f2`.`recipient` 
WHERE (`f1`.`recipient` = 2 OR `f2`.`sender` = 2); 

工作這兩種情況下(問題基本上是,我怎麼能做到這一點沒有工會?):

SELECT `accounts`.*, 
    IFNULL(`f1`.`sender`,  `f2`.`sender`)  AS `sender`, 
    IFNULL(`f1`.`recipient`,  `f2`.`recipient`)  AS `recipient`, 
    IFNULL(`f1`.`date_sent`,  `f2`.`date_sent`)  AS `date_sent`, 
    IFNULL(`f1`.`date_reviewed`, `f2`.`date_reviewed`) AS `date_reviewed`, 
    IFNULL(`f1`.`accepted`,  `f2`.`accepted`)  AS `accepted` 
FROM `accounts` 
    LEFT JOIN `friendships` AS `f1` ON `accounts`.`id` = `f1`.`sender` 
    RIGHT JOIN `friendships` AS `f2` ON `accounts`.`id` = `f2`.`recipient` 
WHERE (`f1`.`recipient` = 1 OR `f2`.`sender` = 1) 
UNION 
SELECT `accounts`.*, 
    IFNULL(`f1`.`sender`,  `f2`.`sender`)  AS `sender`, 
    IFNULL(`f1`.`recipient`,  `f2`.`recipient`)  AS `recipient`, 
    IFNULL(`f1`.`date_sent`,  `f2`.`date_sent`)  AS `date_sent`, 
    IFNULL(`f1`.`date_reviewed`, `f2`.`date_reviewed`) AS `date_reviewed`, 
    IFNULL(`f1`.`accepted`,  `f2`.`accepted`)  AS `accepted` 
FROM `accounts` 
    RIGHT JOIN `friendships` AS `f1` ON `accounts`.`id` = `f1`.`sender` 
    LEFT JOIN `friendships` AS `f2` ON `accounts`.`id` = `f2`.`recipient` 
WHERE (`f1`.`recipient` = 1 OR `f2`.`sender` = 1); 

SCHEMA CREATION:

CREATE TABLE `accounts` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `status` tinyint(4) DEFAULT '0', 
    `type` varchar(25) NOT NULL, 
    `username` varchar(25) NOT NULL, 
    `first_name` varchar(80) NOT NULL, 
    `last_name` varchar(80) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1; 

/*Data for the table `accounts` */ 

insert into `accounts` 
(`id`,`status`,`type`,`username`,`first_name`,`last_name`) 
values 
(1,1,'writer','user1','User','One'), 
(2,1,'writer','user2','User','Two'), 
(3,1,'publisher','user3','User','Three'); 

CREATE TABLE `friendships` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `sender` int(11) NOT NULL, 
    `recipient` int(11) NOT NULL, 
    `date_sent` datetime DEFAULT NULL, 
    `date_reviewed` datetime DEFAULT NULL, 
    `accepted` int(11) DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1; 

/*Data for the table `friendships` */ 

insert into `friendships` 
(`id`,`sender`,`recipient`,`date_sent`,`date_reviewed`,`accepted`) 
values (3,2,1,'2013-07-16 20:54:46',NULL,NULL); 

回答

1

請試試query。我刪除了兩個連接。只需要一個連接,雙方都可以工作。

SELECT `accounts`.*, `f1`.`sender` AS `sender`,`f1`.`recipient` AS `recipient`,`f1`.`date_sent` AS `date_sent`, `f1`.`date_reviewed` AS `date_reviewed`,`f1`.`accepted` AS `accepted` FROM `accounts` JOIN `friendships` AS `f1` ON (`accounts`.`id` = `f1`.`sender` or `accounts`.`id` = `f1`.`recipient`) WHERE if(`f1`.`recipient` = 1, `f1`.`sender` , if(`f1`.`sender` = 1, `f1`.`recipient` , 0)) = `accounts`.`id`; 
+0

謝謝;我結束了一些非常相似的事情,就在我接受這個之前,你能解釋爲什麼你用if來做,而不僅僅是http://pastie.org/8145449 – Hailwood

+0

其實我對此沒有太多的瞭解,我只是寫它就是這樣。任何方式你的代碼也很好。 – Pramod