Необходимо агрегировать результаты запроса для не точного совпадающего имени - PullRequest
0 голосов
/ 21 февраля 2020

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

Запрос выглядит следующим образом:

SELECT partner, COUNT(*) AS Total
FROM database.data
GROUP BY 1;

Выходные данные выглядят следующим образом:

partner  | total
---------+------
X        | 5
Y        | 3
Z        | 2
X aa     | 6
aa X     | 7
Y aa     | 1

Что мне нужно сделать, так это партнеры типа X, X aa, aa X нужно считать вместе в одном ряду (то же самое для Y и Y aa. Я попытался поиграть с добавлением функции HAVING в конце, но не смог заставить ее работать и не уверен, что это на самом деле правильный для использования.

Буду признателен за любую помощь! Спасибо!

Ответы [ 3 ]

0 голосов
/ 21 февраля 2020

Я думаю, что это должно сделать это:

SELECT d1.partner, COUNT(*) AS Total
FROM (SELECT * FROM database.data d1
    WHERE CHAR_LENGTH(d1.partner) = 1
    GROUP BY d1.partner
    ) d1
-- i
LEFT JOIN database.data d2 ON
        -- get x in aa x and x aa
        d2.partner LIKE CONCAT('%', d1.partner, '%')
-- remoove x aa and aa x from the count table
GROUP BY d1.partner;

С фиктивными данными:

CREATE TABLE IF NOT EXISTS tmp_mock_data
SELECT * FROM (
                  SELECT 'X' partner
                  UNION ALL
                  SELECT 'Y'
                  UNION ALL
                  SELECT 'Z'
                  UNION ALL
                  SELECT 'Y aa'
                  UNION ALL
                  SELECT 'Z aa'
                  UNION ALL
                  SELECT 'X aa'
                  UNION ALL
                  SELECT 'aa Z'
                  UNION ALL
                  SELECT 'aa Y'
                  UNION ALL
                  SELECT 'aa X'
              ) A
CROSS JOIN (SELECT NULL UNION ALL SELECT NULL) B;
SELECT d1.partner, COUNT(*) AS Total
FROM (SELECT * FROM tmp_mock_data d1
    WHERE CHAR_LENGTH(d1.partner) = 1
    GROUP BY d1.partner
    ) d1
-- i
LEFT JOIN tmp_mock_data d2 ON
        -- get x in aa x and x aa
        d2.partner LIKE CONCAT('%', d1.partner, '%')
-- remoove x aa and aa x from the count table
GROUP BY d1.partner;
DROP TABLE tmp_mock_data;
0 голосов
/ 21 февраля 2020
SELECT partner,COUNT(*) AS Total

FROM(

SELECT (CASE WHEN ASCII(LEFT(partner,1)) BETWEEN 65 AND 90 THEN  LEFT(partner,1) ELSE RIGHT(partner,1) END)  AS partner

FROM database.data)

GROUP BY 1;
0 голосов
/ 21 февраля 2020

Без оптимизации:

WITH RECURSIVE
-- rank by length
cte1 AS ( SELECT partner, total, DENSE_RANK() OVER (ORDER BY LENGTH(partner)) rnk
          FROM  data ),
-- find pairs where partner is a substring of anoter partner
cte2 AS ( SELECT partner, total, rnk, partner short
          FROM cte1
          WHERE rnk = 1
          UNION ALL
          SELECT cte1.partner, 
                 cte1.total, 
                 cte1.rnk, 
                 CASE WHEN LOCATE(cte2.partner, cte1.partner)
                      THEN cte2.partner
                      ELSE cte1.partner
                      END
          FROM cte1, cte2
          WHERE cte1.rnk = cte2.rnk + 1 ),
-- select shortest
cte3 AS ( SELECT partner, 
                 total, 
                 rnk, short, 
                 ROW_NUMBER() OVER (PARTITION BY partner ORDER BY LENGTH(short)) rn
          FROM cte2 )
-- get needed data
SELECT short partner, SUM(total) total
FROM cte3 
WHERE rn = 1
GROUP BY short
ORDER BY partner

скрипка

...