MySQL заказ по взвешенным полям - PullRequest
2 голосов
/ 07 августа 2020

У меня есть таблица тегов содержимого для наших статей, и каждый тег имеет вес от 0 до 100 с целью достижения суммы веса тега каждой статьи примерно 100. Мы не проверяем это, поэтому потенциально статья может иметь меньшая или большая сумма.

Моя структура таблицы:

CREATE TABLE `article_tags` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `article_id` bigint(20) DEFAULT NULL,
  `tag` varchar(20) DEFAULT NULL,
  `weight` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Данные могут выглядеть так:

INSERT INTO `article_tags` (`article_id`, `tag, `weight`)
VALUES
  (1, 'fun', 50),
  (1, 'winter', 50),
  (2, 'fun', 10),
  (2, 'love', 10),
  (2, 'summer', 80)
  (3, 'fun', 40),
  (3, 'love', 50),
  (3, 'summer', 10),

Теперь я хотел бы найти все статьи, соответствующие заданному набору взвешенных тегов.

Допустим, у меня есть теги fun 75% и love 25%. Теперь я хочу найти статью, которая лучше всего соответствует этим тегам и упорядочить по этим подсчетам.

Я ожидаю, что статьи будут выставлены следующим образом:

  • Статья 1: веселье 37,5%
  • Статья 3: веселье 30%, любовь 12,5% = 32,5%
  • Статья 2: веселье 7,5%, любовь 2,5% = 10%

Поскольку я оба принимая во внимание их article_tags веса и принимая во внимание запрошенные веса для поиска тегов.

Можно ли этого достичь с помощью запроса MySQL?

ОБНОВЛЕНИЕ ПО МАТЕМАТИЧЕСКОМУ

Моя математика следующая: В моем примере показана 4-я статья:

INSERT INTO `article_tags` (`article_id`, `tag, `weight`)
VALUES
  (4, 'fun', 75),
  (4, 'love', 25)

Теперь, просматривая эту статью, я хочу найти статьи, связанные с этой 4-й статьей.

Итак, статья 1 соответствует fun 50%, но поскольку моя 4-я статья оценивает только fun как 75%, я вычитаю вес статьи 1: 50 * 0.75 = 37.5.

Может быть, для этот. Моя конечная цель - найти похожие статьи и при этом учитывать вес каждого тега.

1 Ответ

1 голос
/ 14 августа 2020

После вашего последнего обновления.

С помощью этого запроса вы можете найти статью с аналогичным весом в тегах. В конце я помещаю пример.

CREATE TABLE `article_tags` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `article_id` bigint(20) DEFAULT NULL,
  `tag` varchar(20) DEFAULT NULL,
  `weight` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `article_tags` (`article_id`, `tag`, `weight`)
VALUES
  (1, 'fun', 50),
  (1, 'winter', 50),
  (2, 'fun', 10),
  (2, 'love', 10),
  (2, 'summer', 80),
  (3, 'fun', 40),
  (3, 'love', 50),
  (3, 'summer', 10)
INSERT INTO `article_tags` (`article_id`, `tag`, `weight`)
VALUES
  (4, 'fun', 75),
  (4, 'love', 25)
SELECT 
    at1.`article_id`, `tag`, (`weight` / 100 * proc_per_id) correlated_weight
FROM
    article_tags at1
        INNER JOIN
    (SELECT 
        `article_id`, SUM(`weight`) / COUNT(*) proc_per_id
    FROM
        article_tags
    GROUP BY `article_id`) at2 ON at1.`article_id` = at2.`article_id`
article_id | tag    | correlated_weight
---------: | :----- | ----------------:
         1 | fun    |       25.00000000
         1 | winter |       25.00000000
         2 | fun    |        3.33333000
         2 | love   |        3.33333000
         2 | summer |       26.66664000
         3 | fun    |       13.33332000
         3 | love   |       16.66665000
         3 | summer |        3.33333000
         4 | fun    |       37.50000000
         4 | love   |       12.50000000
SELECT `article_id`,  SUM(`weight`)/COUNT(*) proc_per_id FROM article_tags GROUP BY `article_id`
article_id | proc_per_id
---------: | ----------:
         1 |     50.0000
         2 |     33.3333
         3 |     33.3333
         4 |     50.0000
SELECT `tag`,  SUM(`weight`)/COUNT(*) proc_per_tag, COUNT(*) count_tag FROM article_tags GROUP BY `tag`
tag    | proc_per_tag | count_tag
:----- | -----------: | --------:
fun    |      43.7500 |         4
winter |      50.0000 |         1
love   |      28.3333 |         3
summer |      45.0000 |         2
#All Articles that have Tag fun and a corrlated weight betweeen 20 aand 40
SELECT 
    `article_id`
FROM
    (SELECT 
        at1.`article_id`,
            `tag`,
            (`weight` / 100 * proc_per_id) correlated_weight
    FROM
        article_tags at1
    INNER JOIN (SELECT 
        `article_id`, SUM(`weight`) / COUNT(*) proc_per_id
    FROM
        article_tags
    GROUP BY `article_id`) at2 ON at1.`article_id` = at2.`article_id`) t1
WHERE
    `tag` = 'fun'
        AND correlated_weight BETWEEN 20 AND 40
| article_id |
| ---------: |
|          1 |
|          4 |

db <> fiddle здесь

Выберите один из них

SELECT 
    at1.`article_id`, at1.`tag`, (at1.`weight` / 100 * at2. `weight` ) correlated_weight
FROM
    article_tags at1
        INNER JOIN
    (SELECT 
        tag ,`weight` 
    FROM
        article_tags
    WHERE `article_id` = 4) at2 ON at1.`tag` = at2.`tag`AND at1.`tag` = 'fun' AND at1.`article_id` = 1
article_id | tag | correlated_weight
---------: | :-- | ----------------:
         1 | fun |           37.5000
SELECT 
    at1.`article_id`, at1.`tag`, (at1.`weight` / 100 * at2. `weight` ) correlated_weight
FROM
    article_tags at1
        INNER JOIN
    (SELECT 
        tag ,`weight` 
    FROM
        article_tags
    WHERE `article_id` = 4) at2 ON at1.`tag` = at2.`tag`
WHERE at1.`tag` = 'fun' AND at1.`article_id` = 1
article_id | tag | correlated_weight
---------: | :-- | ----------------:
         1 | fun |           37.5000
SELECT 
    at1.`article_id`
    , at1.`tag`
    , (at1.`weight` / 100 * (SELECT `weight` FROM  article_tags
                             WHERE `article_id` = 4 AND tag = at1.tag) ) correlated_weight
FROM
    article_tags at1
WHERE at1.`tag` = 'fun' AND at1.`article_id` = 1
article_id | tag | correlated_weight
---------: | :-- | ----------------:
         1 | fun |           37.5000

db <> скрипка здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...