所以我在这个简化的例子中有两个表:人和房子。人们可以拥有多个房子,所以我有一个People.Houses字段,这是一个带逗号分隔符的字符串(例如:“House1,House2,House4”)。房子里面可以有多个人,所以我有一个Houses.People字段,它的工作方式相同(“Sam,Samantha,Daren”)。
我想找到People表中与给定房屋中人员姓名相对应的所有行,反之亦然,因为房屋属于人。但我无法弄清楚如何做到这一点。
这是我到目前为止所提出的:
SELECT People.*
FROM Houses
LEFT JOIN People ON Houses.People Like CONCAT(CONCAT('%', People.Name), '%')
WHERE House.Name = 'SomeArbitraryHouseImInterestedIn'
但是我得到了一些误报(例如:当我想要Samantha时,Sam和Samantha可能都会被抓住。还有House3,House34和House343,当我想要House343时)。
我想我可能会尝试编写一个SplitString函数,这样我就可以将一个字符串(使用一个分隔符列表)拆分成一个集合,并在该集合上做一些子查询,但是MySQL函数不能将表作为返回值。
同样,你不能将数组存储为字段,并且从我收集的内容中,长字符串中的逗号分隔元素似乎是解决此问题的常用方法。
我可以想出一些不同的方法来获得我想要的东西,但我想知道是否有一个不错的解决方案。
答案 0 :(得分:6)
同样,你不能将数组存储为字段,并且从我收集的内容中,长字符串中的逗号分隔元素似乎是解决此问题的常用方法。
我希望那不是真的。在SQL数据库中表示“数组”不应采用逗号分隔格式,但可以使用junction table正确解决问题。以逗号分隔的字段在关系数据库中应该没有位置,它们实际上违反了first normal form。
您希望表架构看起来像这样:
CREATE TABLE people (
id int NOT NULL,
name varchar(50),
PRIMARY KEY (id)
) ENGINE=INNODB;
CREATE TABLE houses (
id int NOT NULL,
name varchar(50),
PRIMARY KEY (id)
) ENGINE=INNODB;
CREATE TABLE people_houses (
house_id int,
person_id int,
PRIMARY KEY (house_id, person_id),
FOREIGN KEY (house_id) REFERENCES houses (id),
FOREIGN KEY (person_id) REFERENCES people (id)
) ENGINE=INNODB;
然后搜索人员就像这样容易:
SELECT p.*
FROM houses h
JOIN people_houses ph ON ph.house_id = h.id
JOIN people p ON p.id = ph.person_id
WHERE h.name = 'SomeArbitraryHouseImInterestedIn';
不再有误报,他们从此过上幸福的生活。
答案 1 :(得分:5)
很好的解决方案是重新设计您的架构,以便您拥有以下表格:
People
------
PeopleID (PK)
...
PeopleHouses
------------
PeopleID (PK) (FK to People)
HouseID (PK) (FK to Houses)
Houses
------
HouseID (PK)
...
答案 2 :(得分:3)
对于您当前的问题,FIND_IN_SET function是您要用于加入的内容:
SELECT p.*
FROM PEOPLE p
JOIN HOUSES h ON FIND_IN_SET(p.name, h.people)
WHERE h.name = ?
SELECT h.*
FROM HOUSES h
JOIN PEOPLE p ON FIND_IN_SET(h.name, p.houses)
WHERE p.name = ?
通过添加一个表来将房屋链接到人,可以对此进行正确建模,因为您可能在两个表中存储冗余关系:
CREATE TABLE people_houses (
house_id int,
person_id int,
PRIMARY KEY (house_id, person_id),
FOREIGN KEY (house_id) REFERENCES houses (id),
FOREIGN KEY (person_id) REFERENCES people (id)
)
答案 3 :(得分:0)
问题是你必须使用另一个模式,比如@RedFilter提出的模式。您可以将其视为:
人员表: 的peopleid otherFields
房屋表: HouseID otherFields
所有权表: 的peopleid HouseID otherFields
希望有所帮助,
答案 4 :(得分:0)
您好,您只需更改表名称的位置,左侧是人,然后右侧是Houses:
选择人物。* 来自人民 LEFT JOIN Houses on Houses.People like CONCAT(CONCAT('%',People.Name),'%') 在哪里House.Name ='SomeArbitraryHouseImInterestedIn'