2

语境

我正在尝试在我的网站上创建一个“提要”系统,用户可以在其中访问他们的提要并查看他们可以在网站上执行的不同操作的所有新通知。例如,在“feed”部分,用户可以查看他们关注的用户是否创建了文章,以及用户是否对文章发表了评论。我当前的提要系统仅使用两个单独的查询来获取此信息。但是,我想将这两个查询合并为一个,以便用户可以按时间顺序查看他们关注的人的活动。我的系统现在的工作方式是,我从用户关注的每个人那里获得五篇文章并将其放入“提要”部分,然后获得五篇文章评论并将其发布在“提要”部分的同一区域中。我不想将查询分开,而是将它们组合起来,

问题

首先,如果您想重新创建表,让我向您展示我的表创建代码。首先要做的是创建一个users表,我articlesarticlecomments表引用它:

CREATE TABLE users (
    idUsers int(11) AUTO_INCREMENT PRIMARY KEY NOT NULL,
    uidUsers TINYTEXT NOT NULL,
    emailUsers VARCHAR(100) NOT NULL,
    pwdUsers LONGTEXT NOT NULL,
    created DATETIME NOT NULL, 
    UNIQUE (emailUsers),
    FULLTEXT(uidUsers)
) ENGINE=InnoDB;

接下来,让我们创建articles表:

CREATE TABLE articles (
    article_id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
    title TEXT NOT NULL,
    article TEXT NOT NULL,
    date DATETIME NOT NULL,
    idUsers int(11) NOT NULL,
    topic VARCHAR(50) NOT NULL,
    published VARCHAR(50) NOT NULL,
    PRIMARY KEY (article_id),
    FULLTEXT(title, article),
    FOREIGN KEY (idUsers) REFERENCES users (idUsers) ON DELETE CASCADE ON UPDATE 
CASCADE
) ENGINE=InnoDB;

最后,我们需要articlecomments表格:

CREATE TABLE articlecomments (
    comment_id INT(11) AUTO_INCREMENT PRIMARY KEY NOT NULL,
    message TEXT NOT NULL,
    date DATETIME NOT NULL,
    article_id INT(11) UNSIGNED NOT NULL,
    idUsers INT(11) NOT NULL,
    seen TINYTEXT NOT NULL,
    FOREIGN KEY (article_id) REFERENCES articles (article_id) ON DELETE CASCADE ON UPDATE CASCADE,
    FOREIGN KEY (idUsers) REFERENCES users (idUsers) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB;

为了为本示例充分填充表,我们将使用以下语句:

INSERT INTO users (uidUsers, emailUsers, pwdUsers, created) VALUES ('genericUser', 'genericUser@hotmail.com', 'password', NOW());

INSERT INTO articles (title, article, date, idUsers, topic, published) VALUES ('first article', 'first article contents', NOW(), '1', 'other', 'yes');
INSERT INTO articles (title, article, date, idUsers, topic, published) VALUES ('second article', 'second article contents', NOW(), '1', 'other', 'yes');
INSERT INTO articles (title, article, date, idUsers, topic, published) VALUES ('third article', 'third article contents', NOW(), '1', 'other', 'yes');

INSERT INTO articlecomments (message, date, article_id, idUsers, seen) VALUES ('first message', NOW(), '1', '1', 'false');
INSERT INTO articlecomments (message, date, article_id, idUsers, seen) VALUES ('second message', NOW(), '1', '1', 'false');
INSERT INTO articlecomments (message, date, article_id, idUsers, seen) VALUES ('third message', NOW(), '1', '1', 'false');

我用来从articlesarticlecomments表中获取数据的两个查询如下:

查询一:

SELECT 
  articles.article_id, articles.title, articles.date, 
  articles.idUsers, users.uidUsers 
FROM articles 
JOIN users ON articles.idUsers = users.idUsers 
WHERE articles.idUsers = '1' AND articles.published = 'yes' 
ORDER BY articles.date DESC 
LIMIT 5

查询 2:

SELECT
   articlecomments.comment_id, articlecomments.message,
   articlecomments.date, articlecomments.article_id, users.uidUsers 
FROM articlecomments 
JOIN users ON articlecomments.idUsers = users.idUsers 
WHERE articlecomments.idUsers = '1' 
ORDER BY articlecomments.date DESC 
LIMIT 5

我将如何组合这两个包含不同信息和列的查询,以便根据创建日期(分别为articles.date和)对它们进行排序?articlecomments.date我希望它们在不同的行中,而不是在同一行中。因此,应该就像我分别查询它们并将结果行简单地组合在一起一样。如果有三篇文章和三篇文章评论,我希望总共返回六行。

这就是我想要的样子。鉴于有三篇文章和三篇文章评论,并且评论是在文章之后创建的,这就是结合上面的查询后的结果应该是这样的(我不确定考虑到不同的列名,这种描述是否可能,但我'想知道是否可以完成类似的事情):

+-------------------------------+-------------------+---------------------+----------------------------------------------------------------+---------+-------------+
| id (article_id or comment_id) |   title/message   |        date         | article_id (because it is referenced in articlecomments table) | idUsers |  uidUsers   |
+-------------------------------+-------------------+---------------------+----------------------------------------------------------------+---------+-------------+
|                             1 | first message     | 2020-07-07 11:27:15 |                                                              1 |       1 | genericUser |
|                             2 | second message    | 2020-07-07 11:27:15 |                                                              1 |       1 | genericUser |
|                             3 | third message     | 2020-07-07 11:27:15 |                                                              1 |       1 | genericUser |
|                             2 |    second article | 2020-07-07 10:47:35 |                                                              2 |       1 | genericUser |
|                             3 |    third article  | 2020-07-07 10:47:35 |                                                              3 |       1 | genericUser |
|                             1 |    first article  | 2020-07-07 10:46:51 |                                                              1 |       1 | genericUser |
+-------------------------------+-------------------+---------------------+----------------------------------------------------------------+---------+-------------+

我尝试过的事情

我读过这可能涉及JOINUNION操作员,但我不确定如何在这种情况下实现它们。我确实尝试通过简单地使用来组合这两个查询(Query 1) UNION (Query 2),它首先告诉我我的两个查询中的列数不同,所以我不得不从我的查询中删除该idUsers列。articlecomments这实际上让我有点接近,但它的格式不正确:

+------------+-------------------+---------------------+---------+-------------+
| article_id |       title       |        date         | idUsers |  uidUsers   |
+------------+-------------------+---------------------+---------+-------------+
|          2 | first message     | 2020-07-07 10:47:35 |       1 | genericUser |
|          3 | third article     | 2020-07-07 10:47:35 |       1 | genericUser |
|          1 | first article     | 2020-07-07 10:46:51 |       1 | genericUser |
|          1 |    second article | 2020-07-07 11:27:15 |       1 | genericUser |
|          2 |    third article  | 2020-07-07 11:27:15 |       1 | genericUser |
|          3 |    first article  | 2020-07-07 11:27:15 |       1 | genericUser |
+------------+-------------------+---------------------+---------+-------------+

有任何想法吗?让我知道是否有任何混淆。谢谢。

Server type: MariaDB

Server version: 10.4.8-MariaDB - mariadb.org binary distribution

4

3 回答 3

4

这看起来像 MySQL。你可以这样做:

select * from (SELECT articles.article_id as id_article_comment, articles.title as title_message, articles.date as created, 'article' AS contenttype, articles.article_id as article_id, articles.idUsers, users.uidUsers FROM articles JOIN users ON articles.idUsers = users.idUsers WHERE articles.idUsers = '1' AND articles.published = 'yes' ORDER BY articles.date DESC LIMIT 5) a
union all
select * from (SELECT articlecomments.comment_id, articlecomments.message, articlecomments.date, 'article comment' AS contenttype, articlecomments.article_id, articlecomments.idUsers, users.uidUsers FROM articlecomments JOIN users ON articlecomments.idUsers = users.idUsers WHERE articlecomments.idUsers = '1' ORDER BY articlecomments.date DESC LIMIT 5) b
order by created DESC

请参阅此处的示例:https ://dbfiddle.uk/?rdbms=mysql_5.7&fiddle=26280a9c1c5f62fc33d00d93ab84adf3

结果如下:

id_article_comment | 标题信息 | 创建 | article_id | uid 用户   
-----------------: | :------------- | :----------------- | ---------: | :----------
                 1 | 第一篇 | 2020-07-09 05:59:18 | 1 | 通用用户
                 2 | 第二篇 | 2020-07-09 05:59:18 | 1 | 通用用户
                 3 | 第三篇 | 2020-07-09 05:59:18 | 1 | 通用用户
                 1 | 第一条消息 | 2020-07-09 05:59:18 | 1 | 通用用户
                 2 | 第二条消息 | 2020-07-09 05:59:18 | 1 | 通用用户
                 3 | 第三条消息 | 2020-07-09 05:59:18 | 1 | 通用用户

解释

由于我们想使用order byand limit,我们将从第一行创建一个子查询,并从第一个子查询中选择所有列。我们将在输出中以我们想要的方式命名每个字段。

我们对第二个查询做同样的事情,并union all在它们之间添加一个子句。然后,我们根据创建日期(这是第一个查询中的别名)应用排序,以按照您想要的顺序获得您想要的结果。

如果使用union,将从结果中消除重复行。如果您使用union all,将保留重复的行(如果存在)。union all速度更快,因为它结合了 2 个数据集(只要查询中的列相同。union此外,还必须查找重复的行并将它们从查询中删除。

于 2020-07-09T05:01:14.740 回答
1

你没有提到你正在使用的 MySQL 版本,所以我假设它是一个现代版本(MySQL 8.x)。您可以使用在每个子集上生成一个行号ROW_NUMBER(),然后一个普通的UNION ALL就可以了。

我无法理解您想要的确切顺序,以及第四列的article_id (because it is referenced in articlecomments table)含义。如果您详细说明,我可以相应地调整此答案。

产生您想要的结果集的查询是:

select *
from ( (
  SELECT 
    a.article_id as id, a.title, a.date, 
    a.article_id, u.uidUsers,
    row_number() over(ORDER BY a.date DESC) as rn
  FROM articles a
  JOIN users u ON a.idUsers = u.idUsers 
  WHERE a.idUsers = '1' AND a.published = 'yes' 
  ORDER BY a.date DESC 
  LIMIT 5
  ) union all (
  SELECT
    c.comment_id, c.message, c.date, 
    c.article_id, u.uidUsers,
    5 + row_number() over(ORDER BY c.date DESC) as rn
  FROM articlecomments c
  JOIN users u ON c.idUsers = u.idUsers 
  WHERE c.idUsers = '1' 
  ORDER BY c.date DESC 
  LIMIT 5
  )
) x
order by rn

结果:

id  title           date                 article_id  uidUsers     rn
--  --------------  -------------------  ----------  -----------  --
 1  first article   2020-07-10 10:37:00           1  genericUser   1
 2  second article  2020-07-10 10:37:00           2  genericUser   2
 3  third article   2020-07-10 10:37:00           3  genericUser   3
 1  first message   2020-07-10 10:37:00           1  genericUser   6
 2  second message  2020-07-10 10:37:00           1  genericUser   7
 3  third message   2020-07-10 10:37:00           1  genericUser   8

请参阅db<>fiddle中的运行示例。

于 2020-07-10T01:35:56.560 回答
0

你可以像这样交叉加入=

select select(1) from FROM [job] WITH (NOLOCK)
WHERE MemberCode = 'pay'
    AND CampaignID = '2'

    cross  join

      select(1)
        FROM [product] WITH (NOLOCK)
        WHERE MemberCode = 'pay'
            AND CampaignID = '2'
于 2020-07-07T07:45:21.453 回答