1

ユーザーの友達を取得するクエリがあります

私たちがいる状況を考えると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);
4

1 に答える 1

1

このクエリを試してください。2 つの結合を削除しました。必要な結合は 1 つだけで、両側が機能します。

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`;
于 2013-07-16T11:04:51.533 に答える