Как получить разные значения в одном столбце с несколькими возможными значениями в другом? - PullRequest
3 голосов
/ 19 января 2012

Я пытаюсь разобраться, если это возможно, позвольте мне привести пример. Было бы здорово, если бы вы могли направить меня в правильном направлении, пожалуйста.

Table = names
--------------------
Marks & Spencer
Marks & Spencer
marks & spencer

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

Итак, мой запрос:

SELECT regexp_replace(UPPER(name), '&(amp;)*|\\+', '&', 'gi') AS name FROM names GROUP BY names;

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

Result
----------------
name            original
------------------------
MARKS&SPENCER   Marks & Spencer

Возможно ли это? Потому что на данный момент мне возвращают следующее:

Result
----------------
name            original
------------------------
MARKS&SPENCER   Marks & Spencer
MARKS&SPENCER   Marks & Spencer
MARKS&SPENCER   marks & spencer

Спасибо за чтение, буду очень признателен за помощь.

==========

EDIT

Запрос, который я использую для получения вышеуказанного результата:

SELECT names.name, T.result FROM names 
INNER JOIN 
(
    SELECT DISTINCT regexp_replace(UPPER(name), '&(amp;)*|\\+', '&', 'gi') AS result FROM names 
) AS T 
ON regexp_replace(UPPER(name), '&(amp;)*|\\+', '&', 'gi')=T.result 
GROUP BY T.result, names.name 
ORDER BY T.result ASC

Я использую PostgreSQL, кстати, который может сделать больше, чем MySQL, если что-то меняет?

Ответы [ 3 ]

1 голос
/ 19 января 2012

Вам нужно сгруппировать по новому имени, чтобы получить только одну строку и, если вам все равно, какое оригинальное имя появляется, скомпонуйте его с чем-то вроде min:

SELECT min(name),regexp_replace(UPPER(name), '&(amp;)*|\\+', '&', 'gi') AS name
FROM names
GROUP BY regexp_replace(UPPER(name), '&(amp;)*|\\+', '&', 'gi')
1 голос
/ 19 января 2012

Есть еще возможности для улучшения:

SELECT regexp_replace(upper(name), E'&(?:AMP;)+|\\+', '&', 'g') AS name
     , min(name) AS min_org_name
--   , string_agg(name) AS org_names  -- if you want a list of originals
--   , array_to_string(array_agg(name), ', ') AS org_names -- for pg < 9.0+
     , count(*) AS ct
FROM  (   
    SELECT *
    FROM  (VALUES
          ('Marks & Spencer')
        , ('Marks &amp; Spencer')
        , ('marks &amp; spencer')
        , ('marks &amp; speNceR + sons')
        , ('marks &amp;amp;AMP; speNceR & sons')
       ) AS names(name)
    ) name
GROUP  BY 1;

Основные баллы

  • Улучшение регулярных выражений:
    • заменить &amp;(amp;)* на идентичные &(amp;)+
    • после использования upper() на оригинале флаг 'i' только замедляет выполнение. Скорее шаблон верхнего регистра тоже: &(AMP;)+
    • Использовать скобка без захвата : (?:)
    • Когда вы используете escape-последовательность \\+, используйте правильный синтаксис E''
  • Упростить GROUP BY с помощью позиционного параметра, нет необходимости прописывать его дважды
0 голосов
/ 19 января 2012

В настоящее время вы группируете по исходному полю (вы не можете группировать по полю в выбранном вами списке) .

Хотите одно из них?1006 *

Или ...

SELECT
  name                                                       AS original,
  regexp_replace(UPPER(name), '&amp;(amp;)*|\\+', '&', 'gi') AS name
FROM
  names
GROUP BY
  name,
  regexp_replace(UPPER(name), '&amp;(amp;)*|\\+', '&', 'gi')

Или ...

SELECT
  original,
  name
FROM
(
  SELECT
    name                                                       AS original,
    regexp_replace(UPPER(name), '&amp;(amp;)*|\\+', '&', 'gi') AS name
  FROM
    names
)
  AS clean_data
GROUP BY
  original,
  name
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...