【问题标题】:Many to Many relationship between 3 tables3个表之间的多对多关系
【发布时间】:2020-06-06 13:38:28
【问题描述】:

我刚刚发现 1 个问题没有关于此的答案。

我正在使用 CodeIgniter 4(php 和 MySQL)。

我有 3 个主表(视频、用户和标签)。

我需要在这 3 个表之间建立多对多关系,所以我创建了第 4 个处理该表的表(数据透视表)。

表格:

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;

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

我需要搜索表格并将结果分组到以下结构中(我命名为“项目”的对象)。

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

在数据透视表中,我有 3 个 FK,导致大量“重复”数据,一旦我需要为每个关联标签提供一行,并且用户能够关联他想要多少标签和视频。 (现在我知道为什么存在 NoSQL 数据库了)。

总体思路是:

  • 制作一个“Feed”页面,我将在其中显示最后添加的 50 个项目(问题是一个项目将由 N 个数据库条目组成,所以我不能通过这个数字限制查询)。

  • 创建一个搜索页面,用户可以通过标签或用户搜索所有视频。

我认为(不确定)到目前为止唯一的问题是制作这个“项目”对象。

制作此查询并将其作为此“项目”对象的最佳方法是什么?

SQL 重新创建我的表:

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

【问题讨论】:

  • 感谢您的链接!我编辑了我的帖子并添加了一个带有我的 SQL 代码的链接来重新创建我的表。除此之外,我没有编写任何有用的代码,一旦这更像是一个设计问题而不是代码问题。再次感谢。

标签: php mysql codeigniter object


【解决方案1】:

嗯...原来这花了一些时间,但我找到了解决这个问题的方法。

我没有使用 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.

这里我得到了数据透视表 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();

然后我循环浏览结果:

$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
            )]);



    }

就是这样。所以我的结果是一个包含 N 个对象的数组,每个对象看起来像这样:

[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
                    )

            )

    )

如果有任何改进或更好的方法可以做到这一点,我会很高兴看到。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-14
    • 1970-01-01
    • 2022-10-21
    • 1970-01-01
    相关资源
    最近更新 更多