简体   繁体   English

尝试左连接3个ID可能相同的表,我通过类型定义它

[英]Trying to left join 3 tables where the id could be the same, I am defining it via the type

Okay, so I have 3 tables: 好的,所以我有3张桌子:

users 使用者

CREATE TABLE IF NOT EXISTS `users` (
  `user_id` int(11) NOT NULL,
  `user_username` varchar(25) NOT NULL,
  `user_email` varchar(100) NOT NULL,
  `user_password` varchar(255) NOT NULL,
  `user_enabled` int(1) NOT NULL DEFAULT '1',
  `user_staff` varchar(15) NOT NULL DEFAULT '',
  `user_account_type` varchar(20) NOT NULL DEFAULT '0',
  `user_registerdate` date NOT NULL,
  `user_twofactor` int(11) NOT NULL DEFAULT '0',
  `user_twofackey` varchar(255) NOT NULL,
  `user_forgot_email_code` varchar(255) NOT NULL,
  `user_emailverified` varchar(25) NOT NULL DEFAULT 'unverified',
  `user_banned` varchar(25) NOT NULL DEFAULT 'unbanned',
  `user_has_avatar` int(11) NOT NULL DEFAULT '0',
  `user_has_banner` int(11) NOT NULL DEFAULT '0'
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=latin1;

--
-- Dumping data for table `users`
--

INSERT INTO `users` (`user_id`, `user_username`, `user_email`, `user_password`, `user_enabled`, `user_staff`, `user_account_type`, `user_registerdate`, `user_twofactor`, `user_twofackey`, `user_forgot_email_code`, `user_emailverified`, `user_banned`, `user_has_avatar`, `user_has_banner`) VALUES
(1, 'fhfhfhf', 'lol@gmail.com', 'removed', 1, 'admin', 'Business', '2015-07-21', 0, '0', '0', 'unverified', 'unbanned', 1, 0);

company 公司

CREATE TABLE IF NOT EXISTS `company` (
  `company_id` int(11) NOT NULL,
  `company_name` varchar(100) NOT NULL,
  `company_user` int(11) NOT NULL,
  `company_enabled` varchar(50) NOT NULL DEFAULT 'enabled',
  `company_has_avatar` int(5) NOT NULL DEFAULT '0',
  `company_has_banner` int(5) NOT NULL DEFAULT '0'
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;

--
-- Dumping data for table `company`
--

INSERT INTO `company` (`company_id`, `company_name`, `company_user`, `company_enabled`, `company_has_avatar`, `company_has_banner`) VALUES
(1, 'Rad', 3, 'enabled', 0, 0);

training_company training_company

CREATE TABLE IF NOT EXISTS `training_company` (
  `training_company_id` int(11) NOT NULL,
  `training_company_name` varchar(100) NOT NULL,
  `training_company_user` int(11) NOT NULL,
  `training_company_enabled` varchar(50) NOT NULL DEFAULT 'enabled',
  `training_company_has_avatar` int(5) NOT NULL DEFAULT '0',
  `training_company_has_banner` int(5) NOT NULL DEFAULT '0'
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;

--
-- Dumping data for table `training_company`
--

INSERT INTO `training_company` (`training_company_id`, `training_company_name`, `training_company_user`, `training_company_enabled`, `training_company_has_avatar`, `training_company_has_banner`) VALUES
(1, '123', 3, 'enabled', 0, 0),
(2, '123', 3, 'enabled', 0, 0),
(3, '123', 3, 'enabled', 0, 0);

Each have a profile, that have an incrementing id, so will have the same id, Iam just defining they via type, so user would be user, training would be training and company would be company, I am allowing a user to follow either one. 每个人都有一个配置文件,其ID递增,因此将具有相同的ID,Iam只是通过类型定义它们,因此用户将是用户,培训将是培训,公司将是公司,我允许用户关注其中一个。

SQL 的SQL

SELECT * FROM timeline_status
LEFT JOIN users
  ON timeline_status.timeline_status_user = users.user_id
LEFT JOIN timeline_likes
  ON timeline_status.timeline_status_id = timeline_likes.timeline_likes_main_status
LEFT JOIN friends
  ON timeline_status.timeline_status_user = friends.friends_friend
LEFT JOIN user_personal_information
  ON timeline_status.timeline_status_user = user_personal_information.user_personal_information_user
LEFT JOIN following
  ON timeline_status.timeline_status_user = following.following
WHERE timeline_status_enabled = 'enabled'
AND timeline_status.timeline_status_type = 'user'
AND (timeline_status.timeline_status_user = :status_user
OR friends.friends_user = :friend_user)
AND (timeline_status_privacy = 'onlyme'
AND timeline_status_user = :status_user2
OR timeline_status_privacy = 'public'
OR timeline_status_privacy = 'private')
GROUP BY timeline_status_id
ORDER BY timeline_status_date DESC
LIMIT :start, :end

So I'd want to select from users if type = user, and row exists in followers and/or friends, select from companies or training from followers if type = company or training. 因此,我想从类型为user的用户中选择用户,并且在追随者和/或朋友中存在行,从类型为公司或培训的追随者中选择公司或培训。

My status have the company/user/training id, and the type, so I know which table to select the 'user from' 我的状态包含公司/用户/培训ID和类型,因此我知道从哪个表中选择“用户”

my following table; 我的下表;

CREATE TABLE IF NOT EXISTS `following` (
  `following_id` int(11) NOT NULL,
  `following_user` int(11) NOT NULL,
  `following_type` varchar(50) NOT NULL,
  `following` int(11) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1;

--
-- Dumping data for table `following`
--

INSERT INTO `following` (`following_id`, `following_user`, `following_type`, `following`) VALUES
(5, 3, 'company', 14),
(8, 3, 'training', 1);

timeline status: 时间轴状态:

CREATE TABLE IF NOT EXISTS `timeline_status` (
  `timeline_status_id` int(11) NOT NULL,
  `timeline_status_user` int(11) NOT NULL,
  `timeline_status_privacy` varchar(25) NOT NULL DEFAULT 'public',
  `timeline_status_type` varchar(25) NOT NULL DEFAULT 'user',
  `timeline_status_post` text NOT NULL,
  `timeline_status_date` datetime NOT NULL,
  `timeline_status_enabled` varchar(25) NOT NULL DEFAULT 'enabled'
) ENGINE=InnoDB AUTO_INCREMENT=123 DEFAULT CHARSET=latin1;

--
-- Dumping data for table `timeline_status`
--

INSERT INTO `timeline_status` (`timeline_status_id`, `timeline_status_user`, `timeline_status_privacy`, `timeline_status_type`, `timeline_status_post`, `timeline_status_date`, `timeline_status_enabled`) VALUES
(98, 3, 'private', 'user', 'hello', '2015-10-02 16:29:48', 'enabled'),
(99, 3, 'onlyme', 'user', 'yo', '2015-10-02 16:29:56', 'enabled'),
(100, 3, 'public', 'user', 'fghyjt', '2015-10-02 17:51:28', 'enabled'),
(101, 1, 'private', 'training', 'teest..', '2015-10-03 14:26:45', 'enabled'),
(102, 15, 'public', 'company', 'hello', '2015-10-06 13:32:30', 'enabled');

So how can I do it so if the following type = company select from company, if following tye = training select from training, and if following type = user, keep the sql how it is at the moment. 因此,如果以下类型=公司从公司中选择,如果遵循tye =培训从培训中选择,并且如果遵循类型=用户,那么如何保持sql的状态,我该怎么做。 Because at the moment, I am following a company with the id of 1, but there's a user with an id of 1 too, so I am getting their statuses. 因为此刻,我正在跟踪ID为1的公司,但是也有一个ID为1的用户,所以我要获取其状态。

Your best bet would be to use the UNION operator to mix them all in 1 table, and then query based on type. 最好的选择是使用UNION运算符将它们全部混合在一张表中,然后根据类型进行查询。 For instance, you could do something like this : 例如,您可以执行以下操作:

SELECT f.*, 
    t.training_company_name as name, 
    null as staff,
    t.training_company_enabled as enabled, 
    t.training_company_has_banner as banner, 
    t.training_company_has avatar as avatar 
FROM following f
INNER JOIN training_company t on f.following_user = t.training_company_user AND f.following_type='training'
UNION ALL
SELECT f.*, 
    c.company_name as name, 
    null as staff,
    c.company_enabled as enabled, 
    c.company_has_banner as banner, 
    c.company_has avatar as avatar 
FROM following f
INNER JOIN company c on f.following_user = c.company_user AND c.following_type='company'
UNION ALL
SELECT f.*, 
    u.user_username as name, 
    u.user_staff as staff, 
    u.user_enabled as enabled, 
    u.user_has_banner as banner, 
    u.user_has avatar as avatar 
FROM following f
INNER JOIN users u on f.following_user = c.company_user AND f.following_type='user'

And from there you will have a derived table/view that will look like 从那里,您将获得一个派生的表/视图,看起来像

V_followers(timeline_status_id, timeline_status_user, timeline_status_privacy, timeline_status_type, timeline_status_post, timeline_status_date, timeline_status_enabled, name, staff, enabled, banner, avatar) . V_followers(timeline_status_id, timeline_status_user, timeline_status_privacy, timeline_status_type, timeline_status_post, timeline_status_date, timeline_status_enabled, name, staff, enabled, banner, avatar)

I'm not 100% certain the syntax is MySql-correct though, but the idea remains the same. 我不是100%肯定语法是MySql正确的,但是想法还是一样的。

I think you will need another variable to tell you the type in addition to the user id. 我认为除了用户ID外,您还需要另一个变量来告诉您类型。 Then you can wrap both up in a CASE statement, like so: 然后,您可以将它们包装在CASE语句中,如下所示:

WHERE 
CASE WHEN type = 'USER' THEN timeline_status.timeline_status_user = id
WHEN type = 'FRIENDS' THEN friends.friends_user = id
WHEN type = 'FOLLOWING' THEN following.user = id
END

In your question you actually ask few questions) 在您的问题中,您实际上提出了几个问题)

1) And company and training_company have user, that's why you can join this tables, left join will takes only needed rows and from appropriate tables, and with case you can select needed field: 1)并且companytraining_company都有用户,这就是为什么您可以联接此表,左联接将仅接受所需的行并来自适当的表,并且在这种情况下,您可以选择所需的字段:

select
    u.user_id, u.user_account_type,
    case when u.user_account_type = 'Business' then c.company_name
        else tc.training_company_name
        end as name_of_company
from users u
left join company as c on u.user_id = c.company_user
left join training_company as tc on u.user_id = tc.training_company_user
;

2) Table following contains and users and companies that's why you can do the same: 2)表following包含与userscompanies ,这就是为什么你可以这样做:

select
    f.following_user,
    f.following_type,
    case
        when f.following_type = 'company' then c.company_name
        when f.following_type = 'training' then tc.training_company_name
        else u.user_username
    end as name
from following f
left join users u on f.following_user = u.user_id
-- here you can add inner joins to followers, friends etc
left join company as c on f.following_user = c.company_user
left join training_company as tc on f.following_user = tc.training_company_user
;

3) I think your schema pretty simple and i'm sure that you can use joins to achieve your desires. 3)我认为您的架构非常简单,并且我确信您可以使用联接来实现您的愿望。 I would like emphasize one moment if you have choice: user or company etc - use left join, if you have restrictions users with followers or friends etc - use inner join... (it should work faster)... 我想强调一下,如果您有以下选择:用户或公司等-使用左联接,如果您限制有追随者或朋友的用户等-使用内部联接...(应该更快)...

Hope i correctly understood you, and this info will help you! 希望我正确理解了您,并且此信息对您有帮助!

It seems like you have a situation whereby you have the concept of an entity that can post statuses, and has other information relevant to that. 似乎您处在一种情况下,您具有可以发布状态并具有与此相关的其他信息的实体的概念。

These entities come in three forms; 这些实体有三种形式: user, company, training_company. 用户,公司,training_company。 Each of these forms may have more specific sub details. 这些表格中的每一个都可能具有更具体的子详细信息。

Have you considered placing all the entity info in one table: 您是否考虑过将所有实体信息放在一个表中:

  • entity - id, type, name, enabled, banner, avatar 实体-ID,类型,名称,已启用,横幅,头像

Then implementing a has_one relationship to any information relevant to the sub_type: 然后对与sub_type相关的任何信息实施has_one关系:

  • user - entity_id, ... user specific fields 用户-实体ID,...用户特定字段
  • company - entity_id, .. company specific fields 公司-实体ID,..公司特定字段
  • training_company - entity_id .. training company specific fields training_company-entity_id ..培训公司特定领域

Usually you will be doing one of the following: 通常,您将执行以下操作之一:

  • aggregate stats regarding entities/statuses - select from entity 有关实体/状态的汇总统计信息-从实体中选择
  • lists of statuses - select from entity 状态列表-从实体中选择

  • aggregate stats regarding one specific type - select from type_table join entity 关于一种特定类型的汇总统计信息-从type_table连接实体中选择

  • list inc. 列表公司 detail of one specific type - select from type_table join entity 一种特定类型的详细信息-从type_table连接实体中选择

  • details of one entity - select from type_table join entity 一个实体的详细信息-从type_table连接实体中选择

In the rare case of needing to display full details of a list of entities you can either use a UNION query or just run one query for the entities and then 3 queries on the sub_types WHERE entity_id IN (pulled entity ids).. this data is often paginated anyway, so the performance should be good enough. 在极少数情况下,需要显示实体列表的完整详细信息,您可以使用UNION查询,也可以只对实体运行一个查询,然后对sub_types WHEREEntity_id IN(被拉实体ID)进行3个查询。无论如何还是经常分页,所以性能应该足够好。

We have used this structure in our projects to good effect, be aware it will require more complicated CRUD operations. 请注意,这将需要更复杂的CRUD操作,因此我们在项目中使用了此结构,效果良好。

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

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