ユーザーの友達を取得するクエリがあります。
私たちがいる状況を考えるとuser two
、クエリsent
へのリクエストuser one
は のアカウント情報を返す必要がありますuser one
。(このシナリオの SQLfiddle ) [正常に動作]
私たちがいる状況を考えるとuser one
、クエリrecieved
からのリクエストはuser two
のアカウント情報を返す必要がありますuser two
。(このシナリオの SQLfiddle ) [空の結果を返す]
したがって、リクエストを送信したユーザーである限りクエリは正常に機能しますが、リクエストを受信したユーザーである場合は機能しません。
JOIN、、、を切り替えることでこれを修正できLEFT => RIGHT
ますRIGHT => LEFT
。しかし、それは最初のシナリオを破ります。
2 つのクエリを結合することで、両方を修正できます。(このシナリオの SQLfiddle ) しかし、確かにそれはこれを行うための最も効率的な方法ではありません。基本的な質問: このクエリはどのように作成すればよいですか?
シナリオ 1:
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);
パッチを適用したシナリオ 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);
スキーマの作成:
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);