查询以查找具有多个姓名的人

db2dz4w8  于 2021-07-26  发布在  Java
关注(0)|答案(3)|浏览(266)

我正在做一个相当大的项目,允许我客户网站的用户搜索那些他们过去认识的人,他们可能已经改名了,主要是因为婚姻。基本上,用户用他们曾经使用过的所有名字注册,数据被输入mysql数据库。下一步实际上是创建搜索,它允许用户输入他们记住某人的名字。
这是数据库中的注册示例:

username first0 first1 first2 first3 first4
(email)  Lisa   John   Frank  Sam    Smith

现在,我的查询如下:

SELECT * FROM NAMES
WHERE (
    `names`.`first0` IN ("Lisa", "Sam", "")
    AND `names`.`first1` IN ("Lisa", "Sam", "")
    AND `names`.`first2` IN ("Lisa", "Sam", "")
    AND `names`.`first3` IN ("Lisa", "Sam", "")
    AND `names`.`first4` IN ("Lisa", "Sam", "")

**用搜索表单中输入的数据替换掉那里的确切名称。

此查询不起作用,因为first2= Frank ,不在列表中。如果一个人不知道数据库中输入的每个名字,一切都会中断。
但是,我不想使用or语句,因为我不希望所有的结果都与名称匹配 Lisa 如果有人把 Lisa 只是其中一个名字。
有人知道我该怎么做吗?

qyzbxkaa

qyzbxkaa1#

你在这里受到了不必要的限制。请考虑:

User
UserId, OtherData

UserNames
UserId, Name, Kind

数据如下:

UserId, OtherData
1, Blahblah

UserId, Name, Type
1, Lisa, First 
1, Jane, Middle
1, Smith, Last   
1, Leese, First
1, Jones, Last

丽莎·简·史密斯(lisa jane smith)又名丽斯(leese),结婚后改名为丽莎·简·琼斯(lisa jane jones)
如果您向网站用户显示“输入任意数量的名称并指出它们的种类”,那么您可以运行一个查询来查找包含所提到的所有名称种类的userid
这可以像动态加入或执行条件聚合一样简单
例如,如果网络用户输入“leese”作为firstname,“jones”作为lastname,那么您可以:

SELECT UserID FROM UserNames 
WHERE 
  (name = 'Leese' AND type = 'First') OR
  (name = 'Jones' AND type = 'Last')
GROUP BY
  UserID 
HAVING count(*) = 2 --2 is the number of names entered, leese and jones.  If your where clause had 5 names, this would be 5

或者您可以使用join方法(如果web用户输入3个名称/种类,则使用此方法):

SELECT u1.UserID 
FROM
  UserNames u1 
  INNER JOIN Usernames u2 ON u1.UserID = u2.UserID
  INNER JOIN Usernames u3 ON u1.UserID = u3.UserID
WHERE 
  u1.name = 'Leese' AND u1.type = 'First' AND
  u2.name = 'Jones' AND u2.type = 'Last' AND
  u3.name = 'Smith' AND u3.type = 'Last' AND

在形成动态查询时,不要将这些值连接到sql中。仅仅因为您正在动态构建一个查询,就不能成为将参数化抛出窗口的借口。通过将sql字符串与中的参数占位符连接在一起,然后分别给出参数值来构建sql
用{占位符}插入字符串的语言编写的伪代码(我不知道php):

string fromclause = ""
string whereclause = ""
for i = 0 to webrequest.form.values.length - 1

  string name = webrequest.form.values[i].name
  string type = webrequest.form.values[i].type

  if i == 0 then
    fromclause = fromclause + "Usernames u{i}"
  else
    fromclause = fromclause + " INNER JOIN Usernames u{i} ON u1.UserID = u{i}.UserID

  whereclause = whereclause + " u{i}.Name = @paramName{i} AND u{i}.type = @paramType{i}"

  sqlcommand.parameters.add("@paramName{i}", name)
  sqlcommand.parameters.add("@paramType{i}", type)

next i

sqlcommand.commandtext = "SELECT UserID FROM {fromclause} WHERE {whereclause}"

最后是一个sql命令,该命令全部参数化,参数都是给定值。。

carvr3hs

carvr3hs2#

一个规范化的模式可能是这样的。。。

id username first
 1 (email)  Lisa   
 2 (email)  John   
 3 (email)  Frank  
 4 (email)  Sam    
 5 (email)  Smith
qoefvg9y

qoefvg9y3#

在当前模式下,这样的语句可能会起作用:

SELECT * FROM `names`
WHERE (
    `names`.`first0` = "Lisa" OR
    `names`.`first1` = "Lisa" OR
    `names`.`first2` = "Lisa" OR
    `names`.`first3` = "Lisa" OR
    `names`.`first4` = "Lisa"
) AND (
    `names`.`first0` = "Sam" OR
    `names`.`first1` = "Sam" OR
    `names`.`first2` = "Sam" OR
    `names`.`first3` = "Sam" OR
    `names`.`first4` = "Sam"
)

但正如其他人指出的,您应该有一个不同的规范化模式,如下所示:

CREATE old_firstnames (
  username VARCHAR(255),
  firstname VARCHAR(255),
  timestamp DATETIME,
  PRIMARY KEY (username, firstname, timestamp)
)

您的数据可能是:

username firstname timestamp
(email)  Lisa      1998-02-01
(email)  John      2001-03-02
(email)  Frank     2006-01-04
(email)  Sam       2009-11-13
(email)  Smith     2018-09-01

您可以通过以下方式搜索您的用户:

SELECT * FROM old_firstnames n1
LEFT JOIN old_firstname n2 ON (n1.username = n2.username)
WHERE n1.firstname = "Lisa" AND n2.firstname = "Sam"

相关问题