【问题标题】:How to join a number of fields from one table and compare the result with another field from another table?如何连接一个表中的多个字段并将结果与​​另一个表中的另一个字段进行比较?
【发布时间】:2012-01-27 13:29:36
【问题描述】:

我有以下情况:

table 1 -> publications

table 2 -> users

在出版物的一些详细信息中的表一中,我有 20 个关于作者的字段,确切地说是他们的姓名和姓氏(这些字段:n1, l1, n2, l2, n3, l3... 等等)。

在表二中,我有一个字段,其中包含用户的姓名和姓氏。

我只想显示表 1 中的姓名和姓氏与表 2 中的姓名和姓氏相同的出版物。

到目前为止,这是我的查询:

$sql ="SELECT *, concat_ws(' ',n1,l1), concat_ws(' ',n2,l2) AS my
       FROM #__publications WHERE my IN
       (SELECT name FROM #__users WHERE name = '".$l_user."')";

我知道我的思维方式可能是错误的。你可以帮帮我吗?如果您能给我一些建议,我将不胜感激。

【问题讨论】:

    标签: mysql join concat-ws


    【解决方案1】:

    您应该从 Publications 表中删除作者,并创建一个将用户与 Publications 链接的第三个表。

    PublicationAuthors
    
    PublicationID  int
    UserID int
    

    然后您的查询可以只检查该表以查看用户是否与发布相关联。此外,您可以根据需要拥有尽可能多的作者,而无需向 Publications 添加新列,并且如果有人更改姓名,也不会破坏与 Publications 的关系。

    这是一个示例(我为此使用了 SQL Server,因此可能存在小的语法差异):

    CREATE TABLE Publications(
        [PublicationID] [int] IDENTITY(1,1) NOT NULL,
        [Title] [nvarchar](128) NOT NULL,
        [DatePublished] [DateTime]
    PRIMARY KEY CLUSTERED 
    (
        [PublicationID] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    GO
    
    CREATE TABLE Authors(
        [AuthorID] [int] IDENTITY(1,1) NOT NULL,
        [FirstName] [nvarchar](128) NOT NULL,
        [LastName] [nvarchar](128) NOT NULL
    PRIMARY KEY CLUSTERED 
    (
        [AuthorID] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    GO
    
    
    CREATE TABLE PublicationAuthors(
        [PublicationID] [int],
        [AuthorID] [int]
    PRIMARY KEY CLUSTERED
    (
        [PublicationID] ASC,
        [AuthorID]
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    GO
    
    
    INSERT INTO Publications (Title, DatePublished) VALUES ('Sphere', '5/12/1987')
    INSERT INTO Publications (Title, DatePublished) VALUES ('Jurassic Park', '11/1/1990') 
    INSERT INTO Authors (FirstName, LastName) VALUES ('Michael', 'Chricton')
    INSERT INTO Authors (FirstName, LastName) VALUES ('Andy', 'McKenna')
    INSERT INTO PublicationAuthors (PublicationID, AuthorID) VALUES (1, 1)
    INSERT INTO PublicationAuthors (PublicationID, AuthorID) VALUES (2, 1)
    INSERT INTO PublicationAuthors (PublicationID, AuthorID) VALUES (2, 2)
    
    --All Authors for this Publication
    SELECT p.Title, p.DatePublished, a.FirstName, a.LastName
    FROM Publications p
    INNER JOIN PublicationAuthors pa
       ON pa.PublicationID = p.PublicationID
    INNER JOIN Authors a
       ON a.AuthorID = pa.AuthorID
    WHERE p.PublicationID = 2
    
    --All Publications for this Author
    SELECT p.Title, p.DatePublished, a.FirstName, a.LastName
    FROM Authors a
    INNER JOIN PublicationAuthors pa
       ON pa.AuthorID = a.AuthorID
    INNER JOIN Publications p
       ON pa.PublicationID = p.PublicationID
    WHERE a.AuthorID = 1
    

    然后,当您意识到我拼错了作者的姓氏时,您可以直接更新那一行,而无需触及 Publications 表。

    【讨论】:

    • 感谢您的回答。我不确定我是否理解你。所以我从 Publications 表中删除作者并创建下一个表 PublicationAuthors。接下来我放在那里:the authors’ name and lastname, publication_id, and user_id。一位作者可能有许多出版物,并且该作者可能不是用户,因此在这种情况下,我必须将新列添加到 PublicationAuthors 表中。如果作者写一个新的
    • 如果作者写了一个新的出版物,我应该添加一个新的字段——一个新的publication_id或者在同一个作者的表中添加一个新的记录。
    • 不,您需要将publication_id 从作者/用户表中分离出来。您需要第三个表,它只是作者到出版物的映射。这样,您就有 1 个不同的出版记录和 1 个不同的作者记录。如果该作者附加到另一个出版物,那么您所做的就是将新记录添加到映射表中。在此处阅读有关数据规范化的更多信息:en.wikipedia.org/wiki/Database_normalization
    • 我更新了答案以向您展示我在说什么。它被称为多对多关系。
    • 谢谢。你的帖子对我帮助很大。
    【解决方案2】:

    您可能会发现将用户表设置为包含 user_id 字段作为主键并将其用作发布表中的索引会更容易。

    CREATE TABLE __users
    (
        user_id int(11) unsigned not null auto_increment,
        name varchar(32) not null default '',
        .... snip ....
        PRIMARY KEY (user_id)
    );
    
    CREATE TABLE __publications
    (
        publication_id int(11) unsigned not null auto_increment, 
        user_id1 int(11) unsigned not null default 0,
        user_id2 int(11) unsigned not null default 0,
        n1 varchar(32) not null default '',
        l1 varchar(32) not null default '',
        n2 varchar(32) not null default '',
        l2 varchar(32) not null default '',
        .... snip ....
        PRIMARY KEY (publication_id),
        INDEX user_id1 (user_id1),
        INDEX user_id2 (user_id2)
    );
    
    SELECT p.*,  concat_ws(' ', p.n1, p.l1) AS author1,  concat_ws(' ', p.n2, p.l2) AS author2
    FROM __users AS u
    JOIN __publications AS p ON (u.user_id = p.user_id1 OR u.user_id = p.user_id2)
    WHERE u.name = $1_user
    GROUP BY p.publication_id
    

    或者您可以像这样执行连接:

    SELECT p.*,  concat_ws(' ', p.n1, p.l1) AS author1,  concat_ws(' ', p.n2, p.l2) AS author2
    FROM __users AS u
    JOIN __publications AS p ON (u.name = concat_ws(' ', p.n1, p.l1) OR u.name = concat_ws(' ', p.n2, p.l2))
    WHERE u.name = $1_user
    GROUP BY p.publication_id
    

    【讨论】:

    • 感谢汤姆的回答。我会试试的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多