MySQL从具有多个where子句的多个表中选择并查找find_in_set

时间:2015-05-16 00:44:08

标签: mysql database find-in-set

我在尝试使用MySQL查询避免部分重复结果时出现问题。我承认我在MySQL方面真的很新,但我从SO的研究中学到了我在下面为你设计的模式绝对可以做得更好(用户表的linked_users列应该是一个单独的表)。但是,我现在无法改变它的设置方式。

我尝试返回分配给t2中每个项目的用户ID的用户名或链接到这些用户的用户的用户名。但是,查询为每个项返回两组名称。我认为这种情况正在发生,因为它正在搜索它们两次,并且我试图在SO上阅读关于从多个表中返回多个值的this tutorial,但我似乎无法将我的想法包围在JOINS和UNIONS等等。

我的问题是双重的:

  1. 如何在不改变数据库设置方式的情况下解决此问题该怎么办?
  2. 如何更改数据库以便将来更好地允许这样的查询?
  3. 感谢您的时间。

    架构:

    create table users (user_id int, user_name varchar (55), linked_users varchar (55));
    insert into users( user_id, user_name, linked_users)values(1, 'user1', '2,154,4,45');
    insert into users( user_id, user_name, linked_users)values(2, 'user2', '13,1,200');
    create table t2 (t2_id int, user_id int);
    insert into t2( t2_id, user_id)values(1, 2);
    insert into t2( t2_id, user_id)values(2, 1);
    insert into t2( t2_id, user_id)values(3, 1);
    insert into t2( t2_id, user_id)values(4, 2);
    insert into t2( t2_id, user_id)values(5, 3);
    

    查询:

    SELECT t.*, u.user_name 
    FROM t2 t, users u 
    WHERE t.user_id = u.user_id
    OR find_in_set(t.user_id, u.linked_users) > 0
    

    小提琴:http://sqlfiddle.com/#!9/c5540/10

3 个答案:

答案 0 :(得分:1)

您在同一张表中有多对多的关系。一个用户可以具有许多链接用户,并且用户可以是多于一个用户的链接用户。要表示您需要一个可以调用linked_users的附加表,该表由两列定义:

user_id int foreign key to user_id in users table
linked_user_id int foreign key to user_id in users table

此表的主键应该是user_id和linked_user_id

现在,让我们假设你有1到10个用户,其中1个有5,6,8个作为链接用户,3个有1个,6个,10个作为链接用户。你应该插入

1, 5
1, 6
1, 8
3, 1
3, 6
3, 10

在linked_users中。您的查询变为:

select u1.*, u2.*
from users u1 inner join linked_users lu on u1.user_id = lu.user_id
inner join users u2 on lu.linked_user_id = u2.user_id

如果你必须坚持你的设计

select u1.*, u2.*
from users u1 inner join users u2 on
find_in_set(u2.user_id, u1.linked_users) > 0

答案 1 :(得分:1)

您绝对应该更改表格的结构。正确的结构将使用两个表,一个用于实体(“用户”),另一个用于它们之间的关系:

create table users (
    user_id int not null primary key auto_increment,
    user_name varchar(55)
);

create table userlinks (
    user_id int not null references users(user_id),
    linked_user_id int not null references users(user_id)
);

创建表t2(     t2_id int,     user_id int not null引用用户(user_id) );

你的结构有几个明显的缺陷:

  • 您将整数值存储为字符串表示形式。
  • 您将列表存储在字符串中,而SQL几乎不支持以逗号分隔的列表。
  • 您没有主键或外键的定义。

使用此结构,您可以使用distinct获取给定“t”值的用户列表,而不使用exists,而不使用select u.user_id from users u cross join (select user_id from t2 where t2.tid = 1) t where u.user_id = t.user_id or exists (select 1 from ul where ul.user_id = t.user_id and u.user_id = ul.linked_user_id );

t2

该查询说:“获取用户ID与user_id中相应ID相匹配的所有用户,或者该用户与t2中的select u.user_id from users u cross join (select user_id from t2 where t2.tid = 1) t where u.user_id = t.user_id or find_in_set(u.user_id, (select u.linked_users from users u2 where u2.user_id = t.user_id) ) > 0; 相关联。”

作为一个注释,您也可以通过以下方式对您的结构执行此操作:

 <style type="text/css">

    * {
        font-family: Lucida Sans Unicode, Lucida Grande, sans-serif;
    }


    body {
        background-color: white ;
        color: #543864 ;
		z-index: -10;
		clear: both;
    }

    #topmenu {
        float: left;
        padding-top: 50px;
        position: relative;

 }

    #topmenu ul {
         list-style:none;
        
    }

    #topmenu li {
        float:left;
        padding: 5px 30px 0px 20px;
        margin-right: 20px; 
        border-right: 1px solid #292E37;
        text-decoration: underline;

    }

    a:hover {
        font-size: 20px;
    }

    a:link {
        color: #292E37;
    }


    #name {
        margin-bottom: 5px;
        color: #543864;
        display:inline-block;

    }

    #topcontainer {
        width: 100%;
        height: 60px;
        margin-bottom: 15%;
        font-family: Lucida Grande;
        margin-right: 50px;
        border-radius: 25px;
        float: left;
        position: relative;
        text-align: center;
		padding-bottom: 10%;
		

    }

        

 
     
     #footer {
         
        background-color:#B9B7C4;  
		height: 11%;
		width: 100%;
		z-index: 1;
		position:absolute;
		margin-top: 10%;
		margin-bottom: 10%;
		 
     }

     #wrapper {
      margin-right: auto;
      margin-left: auto;
      width: 960px;
	
     }

     #Header {

         float:left;
		 padding-left: 75px;

     }


       
	 .circlefooter {
	
		 width: 50px;
		 height: 50px;
		 float: left;
		 margin: 25px 25px 0 175px;
		 
		 
	 }

	 .circlefooter p {
	
		 padding-left: 75px;
		 width: 150px;
		 font-size: 12px;
		 
		 
	 }
	 
	 .circlefooter img {
		 
		height: 50px;	 
		float: left;
	 }
	 
	 .circlefooter a:hover {
			 font-size: 12px;
	 }

	 
	

 </style>

答案 2 :(得分:0)

感谢Gordon和Tarik的回复。我尝试了你在我的小提琴中提供的代码,但是无法提取t2信息,所以在弄乱了它之后我发现这个查询解决了我遇到的问题:

SELECT t2.*, u.user_name 
FROM users u, t2 t 
WHERE t.user_id = u.user_id 
AND (t.user_id = '$user_id' 
     OR t.user_id IN 
        (SELECT u2.user_id 
         FROM users u2 
         WHERE find_in_set('$user_id', u2.linked_users)
        )
    )

同样,我知道这不是最好的方法,但由于我无法改变结构,这将有助于达到目的。