На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! информация о разделе
user posted imageДанный раздел предназначается исключительно для обсуждения вопросов использования языка запросов SQL. Обсуждение общих вопросов, связанных с тематикой баз данных - обсуждаем в разделе "Базы данных: общие вопросы". Убедительная просьба - соблюдать "Правила форума" и не пренебрегать "Правильным оформлением своих тем". Прежде, чем создавать тему, имеет смысл заглянуть в раздел "Базы данных: FAQ", возможно там уже есть ответ.

Модераторы: Akina
  
> Изменить параметры запроса поиска.
    Есть поиск по статьям в CMS Joomla (находит статьи с не указанными разделами).

    SELECT * FROM joomla_content WHERE metakey NOT LIKE '%раздел%';

    Ввиду того, что не знаю SQL - прошу переделать запрос под 2 отдельные задачи:
    - найти статьи, в которых указаны только теги вида "раздел";
    - найти статьи, в которых тегов вообще нет.

    Спасибо.
      Цитата Сергей85 @
      - найти статьи, в которых указаны только теги вида "раздел";

      ExpandedWrap disabled
        SELECT * FROM joomla_content WHERE metakey LIKE '%раздел%';
        -- или
        SELECT * FROM joomla_content WHERE metakey = 'раздел';

      Какой из запросов использовать - зависит от того, как именно выглядит содержимое поля тегов.

      Цитата Сергей85 @
      - найти статьи, в которых тегов вообще нет.

      ExpandedWrap disabled
        SELECT * FROM joomla_content WHERE metakey = '';
        -- или
        SELECT * FROM joomla_content WHERE metakey IS NULL;

      Какой из запросов использовать - зависит от того, что пишется в поле тегов при их отсутствии.
        SELECT * FROM joomla_content WHERE metakey LIKE '%раздел%' - находит статьи. Но в них есть иные теги, помимо %раздел%.

        SELECT * FROM joomla_content WHERE metakey = ''; - работает.
          Запости несколько записей и скажи, какие из них надо выбрать запросом.
            Цитата MIF @
            Запости несколько записей и скажи, какие из них надо выбрать запросом.

            Статья 1. Теги: раздел-1, статья, мое.
            Статья 2. Теги: раздел-1.
            Статья 3. Теги: статья, мое.
            Статья 4. Теги: статья2, мое2.
            Статья 5. Теги: раздел-2,раздел-что-угодно.

            Запросом нужно поймать статьи 2 и 5: теги только вида "раздел".
              Имо,здесь регекс нужен.
              Какой тип базы данных?
                Цитата MIF @

                mysql
                  В выборке есть записи с пробелом и без пробела после запятой. В реальной таблице есть оба паттерна?
                    Цитата Сергей85 @
                    mysql

                    А версия? в данной задаче это важно. Например, для версии 8.0.4+ можно разобрать CSV-поле тегов на отдельные теги, получив нормализованное представление, на котором реляционное деление выполняется элементарно.

                    Цитата MIF @
                    Запости несколько записей и скажи, какие из них надо выбрать запросом.

                    Оформи в теге таблицы, чтобы было чётко видно, где начинается и где заканчивается значение для каждого отдельного поля.
                    Сообщение отредактировано: Akina -
                      Цитата MIF @

                      В реальной таблице пробелов рядом с запятой нет.

                      Добавлено
                      Цитата Akina @

                      версия MySQL: 5.6

                      Добавлено
                      Цитата Akina @
                      Цитата MIF @
                      Запости несколько записей и скажи, какие из них надо выбрать запросом.

                      Оформи в теге таблицы, чтобы было чётко видно, где начинается и где заканчивается значение для каждого отдельного поля.

                      Не понял. Теги все хранятся в 1 поле "metakey".
                        Цитата Сергей85 @
                        Не понял. Теги все хранятся в 1 поле "metakey".

                        Не понял - не надо. Но если просят - наверное, не просто так, а?
                        Просто сделай. А потом, если хочется, удивляйся, любопытствуй или переспрашивай.

                        Вот, например, твоя строка:
                        Цитата Сергей85 @
                        Статья 1. Теги: раздел-1, статья, мое.

                        Что у тебя в поле metakey?
                        "Статья 1. Теги: раздел-1, статья, мое."?
                        "Теги: раздел-1, статья, мое."?
                        "раздел-1, статья, мое."?
                          Цитата Akina @
                          "раздел-1, статья, мое."

                          "раздел-1, статья, мое". Поле тегов, называется metakey.
                            Дык есть пробелы или их нет?
                              Возможное решение для версии 5.6.

                              Поле metakey содержит несколько тегов, разделённых запятыми. При этом предполагается, что сами теги запятых не содержат (иначе нет возможности определить, что делает запятая - разделяет два тега или является компонентом одного тега). Также предполагается, что максимально возможное количество тегов в одной записи - ограничено (даже если формально такого ограничения нет, есть физическое ограничение на размер поля и на размер тега, так что реально такое максимально возможное количество существует, пусть и может быть достаточно большим).

                              На указанной версии, которая не поддерживает СТЕ, невозможно динамически генерировать наборы записей в запросе. В то же время задача требует парсинга отдельных тегов по номеру (или итеративного парсинга в хранимой процедуре), для чего необходима таблица чисел от 1 до того самого максимально возможного количества тегов. В принципе решаемо набором подзапросов, но суммарный запрос может оказаться достаточно тяжёлым. Рекомендую один раз создать отдельную таблицу с числами от 1 до максимально возможного количества тегов на поле, или до достаточно большого значения, и затем её использовать. Например, с числами от 1 до 1000, в БД mysql - это снизит нагрузку при выполнении запроса:

                              ExpandedWrap disabled
                                CREATE TABLE mysql.numbers (id INT PRIMARY KEY)
                                SELECT 1 + n1.num + n2.num * 10 + n3.num + 100
                                FROM (SELECT 0 num UNION SELECT 1 UNION ... UNION SELECT 9) n1
                                JOIN (SELECT 0 num UNION SELECT 1 UNION ... UNION SELECT 9) n2
                                JOIN (SELECT 0 num UNION SELECT 1 UNION ... UNION SELECT 9) n3;


                              Теперь задача упрощается. Если максимальное количество тегов не превышает 1000, то запрос

                              ExpandedWrap disabled
                                SELECT j.article_id,
                                       1 + LENGTH(metakey) - LENGTH(REPLACE(metakey, ',', '')) total
                                       SUM(SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(j.metakey, ','), ',', n.id), ',', -1) LIKE 'раздел%') matched
                                FROM joomla_content j
                                JOIN mysql.numbers n
                                GROUP BY j.article_id
                                HAVING ... ;


                              позволяет получить требуемые данные. Расчётное поле matched равно количеству тегов, которые соответствуют шаблону, total - соответственно равно общему количеству тегов. Например, если нужны статьи, которые не содержат других тегов - то для таких статей должно выполняться условие total = matched, и именно его следует поместить в HAVING.

                              Если всё же пробелы возможны, то следует использовать
                              ExpandedWrap disabled
                                SUM(TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(CONCAT(j.metakey, ','), ',', n.id), ',', -1)) LIKE 'раздел%') matched


                              Но запрос всё равно будет тяжёлым. И, что самое плохое, без шансов использовать индексы.

                              Если максимальное количество тегов на поле меньше - следует уменьшить количество чисел в таблице mysql.numbers, а если оно в пределах 10-20, то просто генерировать набор чисел непосредственно в запросе.

                              В общем, если задача достаточно частая и критичная по времени, а бы предложил либо нормализовать данные, либо пойти на переопределение данных и создать отдельную таблицу тегов и таблицу связи статья-тег, обновляемую триггерами. Это сильно упростит решение задачи - но требует изменения структуры хранения.
                              Сообщение отредактировано: Akina -
                                У меня получился вот такой запрос.
                                Только это MS SQL, может для mysql надо чтото подправить.
                                И латиница, мне запросы с кириллицей не интересны.
                                Тест таблица и запрос:
                                ExpandedWrap disabled
                                  DECLARE @T TABLE(metakey varchar(max))
                                   
                                  INSERT INTO @T(metakey) VALUES('razdel-128.')
                                  INSERT INTO @T(metakey) VALUES('me,razdel-12.')
                                  INSERT INTO @T(metakey) VALUES('razdel-128,razdel-me,razdel-16.')
                                  INSERT INTO @T(metakey) VALUES('razdel-128,razdel-merazdel-16.')
                                  INSERT INTO @T(metakey) VALUES('razdel-128,razdel-me,anotherrazdel,razdel-16.')
                                   
                                  SELECT *
                                  FROM @T
                                  WHERE metakey like 'razdel-%'
                                  AND LEN (metakey) - LEN(REPLACE(metakey, ',', ''))=  (LEN(metakey) -  LEN(REPLACE(metakey,',razdel-','')))/8


                                output:
                                ExpandedWrap disabled
                                  razdel-128.
                                  razdel-128,razdel-me,razdel-16.
                                  razdel-128,razdel-merazdel-16.
                                  MIF
                                  Тогда уж
                                  ExpandedWrap disabled
                                    SELECT *
                                    FROM @T
                                    WHERE LEN (metakey) - LEN(REPLACE(metakey, ',', '')) = (LEN(metakey) - LEN(REPLACE(',' + metakey,',razdel-','')) - 1)/8

                                  какой смысл проверять по отдельности первое и остальные вхождения?
                                    Если по полю metakey есть индекс. то мой запрос будет работать быстрее.
                                      К сожалению, ни 1 из запросов не отработал. Написал в ТП: меня сам сервер хостера заблокировал.
                                        Отработал такой. Но вернул все равно 0 строк - при наличии одной статьи с тегами "раздел-идеи,раздел-прочее,раздел-решение".

                                        SELECT *FROM joomla_content
                                        WHERE metakey like 'раздел-%'
                                        AND LENGth (metakey) - LENGth(REPLACE(metakey, ',', ''))= (LENGth(metakey) -
                                        LENGth(REPLACE(metakey,',раздел-','')))/8;

                                        Добавлено
                                        Цитата MIF @

                                        Точки нет в конце тегов. Может, в этом дело? Замена в вашем запросе "8" на "7" не помогает.
                                          Проблема в том, что ты не запостил структуру таблицы. Код запроса зависит от типа поля metakey. Попробуй Заменить /8 на /16 и /1 на /2. Может сработает.
                                          ExpandedWrap disabled
                                            DECLARE @T TABLE(metakey nvarchar(max))
                                             
                                            INSERT INTO @T(metakey) VALUES(N'razdel-128.')
                                            INSERT INTO @T(metakey) VALUES(N'me,razdel-12.')
                                            INSERT INTO @T(metakey) VALUES(N'razdel-128,razdel-me,razdel-16.')
                                            INSERT INTO @T(metakey) VALUES(N'razdel-128,razdel-merazdel-16.')
                                            INSERT INTO @T(metakey) VALUES(N'razdel-128,razdel-me,anotherrazdel,razdel-16.')
                                             
                                            SELECT *
                                            FROM @T
                                            WHERE metakey like 'razdel-%'
                                            AND (LEN (metakey) - LEN(REPLACE(metakey, ',', '')))/2=  (LEN(metakey) -  LEN(REPLACE(metakey,',razdel-','')))/16
                                          Сообщение отредактировано: MIF -
                                            Цитата MIF @


                                            Не сработало.

                                            Что если вручную прописать все теги "раздел-что_то", которые имеются? На примере "раздел-IT".
                                            Прикреплённый файлПрикреплённый файл2020_09_03_180407.png (152,42 Кбайт, скачиваний: 867)

                                            Сообщения были разделены в тему "spam"
                                              SELECT * FROM joomla_content WHERE metakey LIKE 'раздел-%'

                                              Работает в случае, если раздел пишется первым.
                                                Может быть не прав, но срытые символы Вы обрабатываете? Давно не подходил к компу.
                                                  Цитата Bas @
                                                  Может быть не прав, но срытые символы Вы обрабатываете? Давно не подходил к компу.

                                                  Что такое скрытые символы?
                                                    Цитата Сергей85 @
                                                    Что такое скрытые символы?

                                                    Символы, которые не видны при обычном отображении. Например, пробел на конце строки - поди его увидь... Или, скажем, символ, изображение которого в текущем шрифте имеет нулевую ширину. Да мало ли...
                                                      В тегах у меня есть пробелы, но не в названиях разделов.
                                                        Насколько велика таблица joomla_content? Если её задампить и зипануть - приложится к сообщению? чтобы на реальных данных тестировать, а не гадать на кофейной гуще..
                                                          Цитата Akina @
                                                          Насколько велика таблица joomla_content? Если её задампить и зипануть - приложится к сообщению? чтобы на реальных данных тестировать, а не гадать на кофейной гуще..

                                                          У меня проблема уже решена. Вы кому отвечаете?
                                                            Цитата Сергей85 @
                                                            Вы кому отвечаете?

                                                            Bas подживил вопрос - и Вы тут же включились. Мне показалось, что проблема либо не решена, либо решена, но Вы в ней не против покопаться ещё. Нет - так нет, не вопрос.
                                                            0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                            0 пользователей:


                                                            Рейтинг@Mail.ru
                                                            [ Script execution time: 0,0628 ]   [ 18 queries used ]   [ Generated: 28.03.24, 10:53 GMT ]