gpt4 book ai didi

sql - 聚合具有优先级的 SQL 行

转载 作者:行者123 更新时间:2023-12-01 00:33:34 25 4
gpt4 key购买 nike

我有一张 table ,里面装满了来自不同来源的元素。一些来源可能具有相同的位置(在我的示例中,不同的 BBC 新闻提要将是不同的来源,但它们都来自 BBC)。每个项目都有一个“唯一”ID,可用于从同一位置识别它。这意味着与站点上相同新闻故事相关但在不同提要下发布的项目将具有相同的“唯一 ID”,但这不一定是全局唯一的。

问题是我想在显示时消除重复项,这样(取决于您看到的提要)您最多只能获得每个故事的一个版本,即使您的两三个提要可能包含指向

我有一个 sources 表,其中包含有关每个源的信息,以及 location_idlocation_precedence 字段。然后我有一个 items 表,其中包含每个项目、它的 unique_idsource_idcontent。具有相同 unique_id 和源 location_id 的项目最多应出现一次,最高源 location_precedence 获胜。

我本以为是这样的:

SELECT `sources`.`name` AS `source`,
`items`.`content`,
`items`.`published`
FROM `items` INNER JOIN `sources`
ON `items`.`source_id` = `sources`.`id` AND `sources`.`active` = 1
GROUP BY `items`.`unique_id`, `sources`.`location_id`
ORDER BY `sources`.`location_priority` DESC

可以解决问题,但这似乎忽略了位置优先级字段。我错过了什么?


示例数据:

CREATE TABLE IF NOT EXISTS `sources` (
`id` int(10) unsigned NOT NULL auto_increment,
`location_id` int(10) unsigned NOT NULL,
`location_priority` int(11) NOT NULL,
`active` tinyint(1) unsigned NOT NULL default '1',
`name` varchar(150) NOT NULL,
`url` text NOT NULL,
PRIMARY KEY (`id`),
KEY `active` (`active`)
);

INSERT INTO `sources` (`id`, `location_id`, `location_priority`, `active`, `name`, `url`) VALUES
(1, 1, 25, 1, 'BBC News Front Page', 'http://newsrss.bbc.co.uk/rss/newsonline_uk_edition/front_page/rss.xml'),
(2, 1, 10, 1, 'BBC News England', 'http://newsrss.bbc.co.uk/rss/newsonline_uk_edition/england/rss.xml'),
(3, 1, 15, 1, 'BBC Technology News', 'http://newsrss.bbc.co.uk/rss/newsonline_uk_edition/technology/rss.xml'),
(4, 2, 0, 1, 'Slashdot', 'http://rss.slashdot.org/Slashdot/slashdot'),
(5, 3, 0, 1, 'The Daily WTF', 'http://syndication.thedailywtf.com/TheDailyWtf');

CREATE TABLE IF NOT EXISTS `items` (
`id` bigint(20) unsigned NOT NULL auto_increment,
`source_id` int(10) unsigned NOT NULL,
`published` datetime NOT NULL,
`content` text NOT NULL,
`unique_id` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_id` (`unique_id`,`source_id`),
KEY `published` (`published`),
KEY `source_id` (`source_id`)
);

INSERT INTO `items` (`id`, `source_id`, `published`, `content`, `unique_id`) VALUES
(1, 1, '2009-12-01 16:25:53', 'Story about Subject One', 'abc'),
(2, 2, '2009-12-01 16:21:31', 'Subject One in story', 'abc'),
(3, 3, '2009-12-01 16:17:20', 'Techy goodness', 'def'),
(4, 2, '2009-12-01 16:05:57', 'Further updates on Foo case', 'ghi'),
(5, 3, '2009-12-01 15:53:39', 'Foo, Bar and Quux in court battle', 'ghi'),
(6, 2, '2009-12-01 15:52:02', 'Anti-Fubar protests cause disquiet', 'mno'),
(7, 4, '2009-12-01 15:39:00', 'Microsoft Bleh meets lukewarm reception', 'pqr'),
(8, 5, '2009-12-01 15:13:45', 'Ever thought about doing it in VB?', 'pqr'),
(9, 1, '2009-12-01 15:13:15', 'Celebrity has 'new friend'', 'pqr'),
(10, 1, '2009-12-01 15:09:57', 'Microsoft launches Bleh worldwide', 'stu'),
(11, 2, '2009-12-01 14:57:22', 'Microsoft launches Bleh in UK', 'stu'),
(12, 3, '2009-12-01 14:57:22', 'Microsoft launches Bleh', 'stu'),
(13, 3, '2009-12-01 14:42:15', 'Tech round-up', 'vwx'),
(14, 2, '2009-12-01 14:36:26', 'Estates 'old news' say government', 'yza'),
(15, 1, '2009-12-01 14:15:21', 'Iranian doctor 'was poisoned'', 'bcd'),
(16, 4, '2009-12-01 14:14:02', 'Apple fans overjoyed by iBlah', 'axf');

查询后的预期内容:

  • 关于主题一的故事
  • 技术好
  • Foo、Bar 和 Quux 在法庭上打架
  • 反富巴尔抗议引起不安
  • Microsoft Bleh 遭遇冷遇
  • 有没有想过用 VB 来实现?
  • 名人有“新 friend ”
  • 微软在全局推出 Bleh
  • 技术综述
  • 政府称房地产“旧闻”
  • 伊朗医生“中毒”
  • 苹果粉丝为 iBlah 高兴不已

我尝试了 Andomar 解决方案的变体,并取得了一些成功:

SELECT      s.`name` AS `source`,
i.`content`,
i.`published`
FROM `items` i
INNER JOIN `sources` s
ON i.`source_id` = s.`id`
AND s.`active` = 1
INNER JOIN (
SELECT `unique_id`, `source_id`, MAX(`location_priority`) AS `prio`
FROM `items` i
INNER JOIN `sources` s ON s.`id` = i.`source_id` AND s.`active` = 1
GROUP BY `location_id`, `unique_id`
) `filter`
ON i.`unique_id` = `filter`.`unique_id`
AND s.`location_priority` = `filter`.`prio`
ORDER BY i.`published` DESC
LIMIT 50

使用 AND s.location_priority = filter.prio 事情几乎如我所愿。因为一个项目可以来自具有相同优先级的多个源,所以项目可以重复。在这种情况下,外部查询上的额外 GROUP BY i.unique_id 可以完成这项工作,我想如果优先级相同,哪个来源“获胜”并不重要。

我曾尝试使用 AND i.source_id = filter.source_id 来代替,这几乎可以工作(即消除了额外的 GROUP BY)但没有给出结果正确的来源。在上面的例子中,它给了我“关于 Foo 案的进一步更新”(来源“BBC News England”)而不是“Foo, Bar and Quux in court battle”(来源“BBC Technology News”)。看看内部的结果查询,我得到:

unique_id: 'ghi'
source_id: 2
prio: 15

请注意,来源 ID 不正确(应为:3)。

最佳答案

Order by只是对行进行排序,它不会在其中进行选择。

过滤掉 location_priority 较低行的方法之一是使用 inner join作为过滤器:

SELECT     s.name, i.content, i.published
FROM items i
INNER JOIN sources s
ON i.source_id = s.id
AND s.active = 1
INNER JOIN (
SELECT unique_id, max(location_priority) as prio
FROM items i
INNER JOIN sources s ON s.id = i.source_id AND s.active = 1
GROUP BY unique_id) filter
ON i.unique_id = filter.unique_id
AND s.location_priority = filter.prio;

另一种选择是 where ... in <subquery>子句,例如:

SELECT     s.name, i.content, i.published
FROM items i
INNER JOIN sources s
ON i.source_id = s.id
AND s.active = 1
WHERE (i.unique_id, s.location_priority) IN (
SELECT unique_id, max(location_priority)
FROM items i
INNER JOIN sources s ON s.id = i.source_id AND s.active = 1
GROUP BY unique_id
);

此问题也称为“选择包含组范围最大值的记录”。 Quassnoi 写了一篇 nice article在上面。

编辑:以相同的优先级打破与多个来源的联系的一种方法是 WHERE带有子查询的子句。这个例子打破了 i.id DESC 的关系:

SELECT     s.name, i.unique_id, i.content, i.published
FROM (
SELECT unique_id, min(location_priority) as prio
FROM items i
INNER JOIN sources s ON s.id = i.source_id AND s.active = 1
GROUP BY unique_id
) filter
JOIN items i
JOIN sources s
ON s.id = i.source_id
AND s.active = 1
WHERE i.id =
(
SELECT i.id
FROM items i
JOIN sources s
ON s.id = i.source_id
AND s.active = 1
WHERE i.unique_id = filter.unique_id
AND s.location_priority = filter.prio
ORDER BY i.id DESC
LIMIT 1
)

Quassnoi 在 selecting records holding group-wise maximum (resolving ties) 上也有一篇文章:)

关于sql - 聚合具有优先级的 SQL 行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1855303/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com