简单的MySQL问题

时间:2009-12-23 02:00:22

标签: sql mysql

我正在开发一个包含人员的MySQL数据库。我的问题是,(我会简化以表明我的观点):

我有三张桌子:

Persons(id int, birthdate date)
PersonsLastNames(id int, lastname varchar(30))
PersonsFirstNames(id int, firstname varchar(30))

id是公共密钥。有姓氏和名字的单独表格,因为一个人可以有许多名字和许多姓氏。

我想创建一个查询,返回所有人,比如一个姓氏。如果我一起去

select birthdate, lastname, firstname from Persons, PersonsLastNames,
PersonsFirstNames where Persons.id = PersonsLastNames.id and
Persons.id = PersonsFirstNames.id and lastName = 'Anderson'

我最终得到一张像

这样的表格
1/1/1970 Anderson Steven //Person 1
1/1/1970 Anderson David  //Still Person 1
2/2/1980 Smith Adam      //Person 2
3/3/1990 Taylor Ed       //Person 3

在提出这个时,我想有

1/1/1970 Anderson Steven David 
2/2/1980 Smith Adam [possibly null?]
3/3/1990 Taylor Ed [possibly null?]

如果需要为一个人保留多个名字或姓氏,我如何加入表格以在结果集中引入新列?

4 个答案:

答案 0 :(得分:1)

SQL不支持查询select-list中的动态列数。您必须根据需要定义尽可能多的列(尽管有*通配符)。

我建议您将多个名称提取为,而不是列。然后编写一些应用程序代码来遍历结果集,并做任何你想做的事情来呈现它们。

答案 1 :(得分:1)

简短的回答是,你做不到。您将始终必须选择固定数量的列。但是,您可以使用ON关键字大大改善查询的语法。例如:

SELECT
    birthdate,
    firstName,
    lastName
FROM
    Persons
    INNER JOIN PersonsLastNames
        ON Persons.id = PersonsLastNames.id
    INNER JOIN PersonsFirstNames
        ON Persons.id = PersonsFirstNames.id
WHERE
    lastName = 'Anderson'
GROUP BY
    lastName, firstName
HAVING
    count(lastName) = 1

当然,我的查询最后会包含一些额外条款,以便只抓住指定了一个姓氏的人,但是你可以随时删除这些。

现在,您可以做的是选择您想要检索的最大数量,并执行以下操作:

SELECT
    birthdate,
    lastName,
    PersonsFirstNames.firstName,
    IFNULL(p.firstName,''),
    IFNULL(q.firstName,'')
FROM
    Persons
    INNER JOIN PersonsLastNames
        ON Persons.id = PersonsLastNames.id
    INNER JOIN PersonsFirstNames
        ON Persons.id = PersonsFirstNames.id
    LEFT JOIN PersonsFirstNames p
        ON Persons.id = p.id
        AND p.firstName <> PersonsFirstNames.firstName
    LEFT JOIN PersonsFirstNames q
        ON Persons.id = q.id
        AND q.firstName <> PersonsFirstNames.firstName
        AND q.firstName <> p.firstName
GROUP BY
    lastName

但我真的不建议这样做。最好的办法是检索多行,然后在你正在使用/开发的任何应用程序中迭代它们。

如果您还不熟悉,请务必在开始之前阅读JOIN类型(左 - 内 - )。希望这会有所帮助。

编辑:在这种情况下,你可能还想考虑一个稍微复杂的GROUP BY子句,例如

GROUP BY
    Persons.id, lastName

答案 2 :(得分:1)

您的应用真的是否需要为每个人处理无限的姓/名?我不知道你的具体需求,但这似乎有点极端。无论...

由于您无法真正返回动态数量的列,因此可以执行以下操作:

SELECT birthdate, lastname, GROUP_CONCAT(firstname SEPARATOR '|') AS firstnames
FROM Persons, PersonsLastNames, PersonsFirstNames
WHERE Persons.id = PersonsLastNames.id
AND Persons.id = PersonsFirstNames.id
GROUP BY Persons.id

这将为每个人返回一个具有姓氏的行,其中(无限制)名字由竖线(|)符号,GROUP_CONCAT函数分隔。

birthdate             lastname   firstnames
---                   ---        ---
1970-01-01 00:00:00   Anderson   Steven|David
1980-02-02 00:00:00   Smith      Adam
1990-03-03 00:00:00   Taylor     Ed

答案 3 :(得分:0)

我认为你能做的最接近的事情是Group By Person.Id,然后进行字符串连接。也许这篇文章会有所帮助: How to use GROUP BY to concatenate strings in MySQL?