简体   繁体   English

3个表之间的多对多关系

[英]Many to Many relationship between 3 tables

I just found 1 question with no answer about this.我刚刚发现 1 个问题对此没有答案。

I'm using CodeIgniter 4 (php and MySQL).我正在使用 CodeIgniter 4(php 和 MySQL)。

I have 3 main tables (videos, users and tags).我有 3 个主表(视频、用户和标签)。

I need to set up a many to many relationship between these 3 tables, so I created a 4th table that handles that (pivot).我需要在这 3 个表之间建立多对多关系,因此我创建了第 4 个处理该表的表(数据透视表)。

Tables:表:

Videos (id, Link)
Users (id, name)
Tags (id, name_tag)
pivot (video_id, user_id, tag_id)
CREATE TABLE `videos` (
  `id` int(10) NOT NULL,
  `link` varchar(250) NOT NULL,
  `title` varchar(250) NOT NULL,
  `main_description` text NOT NULL,
  `aux_description` text NOT NULL,
  `owner` varchar(20) NOT NULL,
  `owner_link` varchar(250) NOT NULL,
  `date` datetime NOT NULL,
  `date_added` datetime NOT NULL,
  `thumbnail` varchar(255) NOT NULL,
  `id_source` int(10) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `videos` (`id`, `link`, `title`, `main_description`, `aux_description`, `owner`, `owner_link`, `date`, `date_added`, `thumbnail`, `id_source`) VALUES
(1, '362454114', '1', '', '', '', '', '0000-00-00 00:00:00', '0000-00-00 00:00:00', '', 1),
(2, '249436458', '2', '', '', '', '', '2018-01-01 00:00:00', '2020-05-30 00:00:00', '', 1),
(3, '172290099', '3', '', '', '', '', '2016-06-26 00:00:00', '0000-00-00 00:00:00', '', 1),
(4, '213585809', '4', '', '', '', '', '2019-09-25 00:00:00', '2020-05-30 00:00:00', '...', 1),
(5, '395267446', '5', '', '', '', '', '2019-09-25 00:00:00', '2020-05-30 00:00:00', '...', 1),
(6, '383823899', '6', '', '', '', '', '2019-09-25 00:00:00', '2020-05-30 00:00:00', '...', 1);

ALTER TABLE `videos`
  ADD PRIMARY KEY (`id`),
  ADD KEY `videos_id_source_foreign` (`id_source`);

ALTER TABLE `videos`
  MODIFY `id` int(10) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7;

ALTER TABLE `videos`
  ADD CONSTRAINT `videos_id_source_foreign` FOREIGN KEY (`id_source`) REFERENCES `sources` (`id`);
COMMIT;

TAGS TABLE  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



CREATE TABLE `tags` (
  `id` int(10) NOT NULL,
  `name` varchar(30) NOT NULL,
  `date` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


INSERT INTO `tags` (`id`, `name`, `date`) VALUES
(0, 'teste1', '2020-05-29 00:00:00'),
(2, 'teste3', '2020-05-28 00:00:00'),
(4, 'teste0', '2020-05-30 00:00:00');


ALTER TABLE `tags`
  ADD PRIMARY KEY (`id`);

ALTER TABLE `tags`
  MODIFY `id` int(10) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7;
COMMIT;


USERS TABLE  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

CREATE TABLE `users` (
  `id` int(10) NOT NULL,
  `rand_id` int(20) NOT NULL,
  `name` varchar(25) NOT NULL,
  `email` varchar(50) NOT NULL,
  `profile_image` varchar(50) NOT NULL,
  `confirmation_link` varchar(125) NOT NULL,
  `confirmation_link_date` datetime NOT NULL,
  `password` varchar(250) NOT NULL,
  `date` datetime NOT NULL,
  `active` tinyint(1) NOT NULL DEFAULT 0
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


INSERT INTO `users` (`id`, `rand_id`, `name`, `email`, `profile_image`, `confirmation_link`, `confirmation_link_date`, `password`, `date`, `active`) VALUES
(1, 1, 'User 1', 'user1@gmail.com', '', '', '0000-00-00 00:00:00', '', '2020-05-12 00:00:00', 1),
(2, 2, 'User 2', 'user2@gmail.com', '', '', '2020-05-12 00:00:00', '', '2020-05-12 00:00:00', 1),
(3, 3, 'User 3', 'user3@gmail.com', '', '', '2020-05-12 00:00:00', '', '2020-05-12 00:00:00', 1),
(4, 4, 'User 4', 'user4@gmail.com', '', '', '2020-05-12 00:00:00', '', '2020-05-12 00:00:00', 1),
(5, 5, 'User 5', 'user5@gmail.com', '', '', '2020-05-12 00:00:00', '', '2020-05-12 00:00:00', 1);

ALTER TABLE `users`
  ADD PRIMARY KEY (`id`);

ALTER TABLE `users`
  MODIFY `id` int(10) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6;
COMMIT;

PIVOT TABLE  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


CREATE TABLE `user_video_relation` (
  `user_id` int(10) NOT NULL,
  `video_id` int(10) NOT NULL,
  `date` datetime NOT NULL,
  `tag_id` int(10) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


INSERT INTO `user_video_relation` (`user_id`, `video_id`, `date`, `tag_id`) VALUES
(1, 1, '2020-05-30 00:00:00', 0),
(2, 2, '2020-05-29 00:00:00', 0),
(3, 3, '2020-05-28 00:00:00', 0),
(4, 4, '2020-05-27 00:00:00', 0),
(5, 5, '2020-05-26 00:00:00', 0),
(1, 6, '2020-05-25 00:00:00', 0),
(2, 1, '2020-05-24 00:00:00', 0),
(3, 2, '2020-05-23 00:00:00', 0),
(4, 3, '2020-05-22 00:00:00', 0),
(5, 4, '2020-05-21 00:00:00', 0),
(1, 5, '2020-05-20 00:00:00', 0);

ALTER TABLE `user_video_relation`
  ADD KEY `user_video_relation_user_id_foreign` (`user_id`),
  ADD KEY `user_video_relation_video_id_foreign` (`video_id`),
  ADD KEY `user_video_relation_tag_id_foreign` (`tag_id`);

ALTER TABLE `user_video_relation`
  ADD CONSTRAINT `user_video_relation_tag_id_foreign` FOREIGN KEY (`tag_id`) REFERENCES `tags` (`id`),
  ADD CONSTRAINT `user_video_relation_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`),
  ADD CONSTRAINT `user_video_relation_video_id_foreign` FOREIGN KEY (`video_id`) REFERENCES `videos` (`id`);
COMMIT;

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

I need to search through the table and group the results in the following structure (a object that I named 'Item').我需要搜索表格并将结果分组到以下结构中(我命名为“项目”的 object)。

item={  
    'User_name'=>'John',  
    'video_link'=>'http://www.youvideo.com/video',  
    'tags'=>['cool','awesome','TooTooTrain']  
}

In the Pivot table I have 3 FK, resulting in a lot of 'duplicated' data, once I need one row for each associated tag, and the user is able to associate how many tags and videos he want.在 Pivot 表中,我有 3 个 FK,导致大量“重复”数据,一旦我需要为每个关联标签设置一行,并且用户能够关联他想要多少标签和视频。 (And now I know why NoSQL DBs exists). (现在我知道为什么 NoSQL DB 存在)。

The General Idea is:总体思路是:

  • Make a 'Feed' page, where I'll show the last 50 added items (the problem is that one single item will be composed by N database entries, so I can't limit the query by this number).制作一个“Feed”页面,我将在其中显示最后添加的 50 个项目(问题是一个项目将由 N 个数据库条目组成,所以我不能通过这个数字限制查询)。

  • Make a search page, where the user will be able to search all the videos by the Tags or Users.创建一个搜索页面,用户可以在其中通过标签或用户搜索所有视频。

I THINK (not sure about that) that the only problem so far is to make this 'Item' object.我认为(不确定)到目前为止唯一的问题是制作这个“项目”object。

What is the best approach to make this Query and result it as this 'Item' object?进行此查询并将其作为“项目”object 的最佳方法是什么?

SQL to recreate my tables: SQL 重新创建我的表:

https://www.writeurl.com/text/j4ssy2fo99pn42qop9k6/87673c6j9psmv9rexvly/qbois6fy15vfpmuswwl1 https://www.writeurl.com/text/j4ssy2fo99pn42qop9k6/87673c6j9psmv9rexvly/qbois6fy15vfpmuswwl1

Well... Turns out that it took some time, but I find a way to solve this.嗯......原来这需要一些时间,但我找到了解决这个问题的方法。

Instead of using 4 tables, I used 5:我没有使用 4 个表,而是使用了 5 个:

Videos (id, Link, etc...)
Users (id, name, etc...)
Tags (id, name_tag, etc...)
pivot (id, video_id, user_id) **Here I removed the tag_id and added a PK
pivot_2 (pivot_id, tag_id) **In this new table, I'm relating the previous pivot table with the Tags table.

在此处输入图像描述

Here I get the results from the Pivot Table 1 joining the Users and Video Tables:在这里,我从 Pivot 表 1 中获得了加入用户和视频表的结果:

$builder = $db->table('user_video_relation');
    $builder_tag=$db->table('tags_video_relation');
    $builder->select('*');        
    $builder->orderBy('user_video_relation.date DESC');
    $builder->join('videos', 'videos.id=user_video_relation.video_id');
    $builder->join('users', 'users.id=user_video_relation.user_id');        
    $query=$builder->get()->getResult();

Then I'm cycling through the results:然后我循环浏览结果:

$items=[]; //This will be an array of Objects, one object to each item.


    foreach ($query as $row){

        //for each result, I run a new query to get the relations from the second Pivot table, filtering by the ID of the Pivot table 1.

        $builder_tag->select('*');
        $builder_tag->where('relation_id',$row->id);
        $builder_tag->join('tags','tags.id=tags_video_relation.tag_id');
        $query_tag=$builder_tag->get()->getResult();
        $tags=[];


//Then, I run another loop in the results from this new query to get all the tags related to the $row and push them to an array.

foreach($query_tag as $tagRow){
            array_push($tags,$tagRow->name);
        }


        //And here I push a New objec into the $items array.
        array_push($items,[new ItemClass(
            $row->video_id,
            $row->title,
            $row->main_description,
            $row->name,
            $row->owner,
            $row->owner_link,
            $row->date,
            $row->date_added,
            $row->thumbnail,
            $row->id_source,
            $tags //array with the results of the second query
            )]);



    }

And that's it.就是这样。 So My result is an array of N objects, and each object looks like this:所以我的结果是一个包含 N 个对象的数组,每个 object 看起来像这样:

[0] => Array
    (
        [0] => App\Models\ItemClass Object
            (
                [id] => 1
                [title] => Office Groove
                [description] => Office Groove Description
                [user] => User's Name
                [owner] => buck
                [owner_link] => https://vimeo.com/buck
                [date] => 2020-05-12 00:00:00
                [date_added] => 2020-05-30 00:00:00
                [thumbnail] => https://i.vimeocdn.com/video/817295847_190x107.jpg
                [id_source] => 1
                [tags] => Array
                    (
                        [0] => Cool
                        [1] => Awesome
                        [1] => TooTooTrain
                    )

            )

    )

If there is any improvement or a better way to do this, I'll be glad to see.如果有任何改进或更好的方法来做到这一点,我会很高兴看到。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM