Ответы пользователя по тегу SQL
  • Как посчитать количество подряд идущих одинаковых записей SQL?

    erge
    @erge
    Примус починяю
    Пытался сделать через ROW_NUMBERS() OVER (PATRITION BY date ORDER BY date, time, check), ну тут, конечно, получается он игнорит check и просто проставляет 1,2,3,4,5.


    вы же написали ниже что группировка по дате и чеку, а делаете PATRITION BY date

    Если добавить PATRITION BY date, check, то он, блин, сортирует по check потом и тоже не то выходит


    правильно, потому что необходимо группировать по тем критериям по которым необходимо и делать сортировку по негруппируемому полю по которому надо сделать счет - time

    ROW_NUMBERS() OVER (PATRITION BY date, check ORDER BY time)

    тогда он посчитает как надо.
    а уж если необходимо еще как-то отсортировать или отобрать, то заворачиваете этот запрос в подзапрос или CTE и делаете из него запрос с WHERE , ORDER и т.п. и т.д.
    Ответ написан
    Комментировать
  • Как настроить кодировку sql developer?

    erge
    @erge
    Примус починяю
    У меня в Oracle SQL Developer так:
    Tools -> Preferences

    Вкладка Envirement: Encoding: UTF-8

    Вкладка Database -> NLS:
    Language: RUSSIAN,
    Territory: RUSSIA,
    Sort: RUSSIAN,
    Date Language: RUSSIAN

    PS: правда девелопер старенький, но не думаю что местоположение настроек сильно отличается.
    Ответ написан
    Комментировать
  • Как правильно собирать данные с разных таблиц БД?

    erge
    @erge
    Примус починяю
    Для построения такого JSON на SQL вам нужны функции json_agg() / json_build_object(), далее обычные запросы с объединениями и группировкой.

    Пример как собрать JSON author
    SELECT json_build_object(
        'account_id', id,
        'first_name', first_name,
        'last_name', last_name
      ) AS author
      FROM accounts

    post собирается как
    json_build_object(
        'post_id', p.id,
        'body', p.body,
        'author', json_build_object(
          'account_id', a.id,
          'first_name', a.first_name,
          'last_name', a.last_name
        )
      )
    при объединении таблиц posts и accounts
    через json_agg собираем в массив
    SELECT json_agg(json_build_object(
        'post_id', p.id,
        'body', p.body,
        'author', json_build_object(
          'account_id', a.id,
          'first_name', a.first_name,
          'last_name', a.last_name
        )
      )) AS posts
      FROM posts p
      JOIN accounts a ON a.id = p.author_id

    комментарии аналогично, но с группировкой по постам - post_id
    SELECT json_agg(json_build_object(
        'comment_id', c.id,
        'body', c.body,
        'author', json_build_object(
          'account_id', a.id,
          'first_name', a.first_name,
          'last_name', a.last_name
        )
      )) AS comments
      FROM comments c
      JOIN accounts a ON a.id = c.author_id
      GROUP BY post_id

    далее объединяем комментарии с постами через post_id = id
    для удобства комментарии вынес в CTE (общее табличное выражение)
    WITH cmts AS (
    SELECT json_agg(json_build_object(
        'comment_id', c.id,
        'body', c.body,
        'author', json_build_object(
          'account_id', a.id,
          'first_name', a.first_name,
          'last_name', a.last_name
        )
      )) AS comments,
      post_id
      FROM comments c
      JOIN accounts a ON a.id = c.author_id
      GROUP BY post_id
    )
    SELECT json_agg(json_build_object(
        'post_id', p.id,
        'body', p.body,
        'author', json_build_object(
          'account_id', a.id,
          'first_name', a.first_name,
          'last_name', a.last_name
        ),
        'comments', COALESCE(c.comments, '[]')
      )) AS "posts with comments"
      FROM posts p
      JOIN accounts a ON a.id = p.author_id
      LEFT JOIN cmts c ON c.post_id = p.id


    см. пример sqlfiddle
    Ответ написан
    1 комментарий
  • SQL Как из перечня свойств выбрать строки по двум совпавшим?

    erge
    @erge
    Примус починяю
    Т.к. СУБД не указана, то в целом решение примерно такое
    1. либо - искомую строку разбиваем на строки (в таблицу) объединяем с исходной таблицей и ищем вхождение каждого параметра (из "разбитой" в таблицу строки) через функцию поиска подстроки, далее группируем и применяем HAVING count(1) >= 2
    2. либо наоборот - каждую строку параметров исходной таблицы разбиваем получаем таблицу матрицу параметров, далее ищем вхождение параметров в искомой строке, и так же группируем и применяем HAVING count(1) >= 2

    надеюсь понятно изложил...

    и опять таки , т.к. СУБД не указана, то применительно к MS SQL это будет выглядеть вот так:

    1.
    WITH f AS (
      SELECT 'PARAM1 PARAM3 PARAM7' as findstr
    ),
    fr AS (
      SELECT t.value AS param
        FROM f
        CROSS APPLY STRING_SPLIT(f.findstr, ' ') t
    )
    SELECT d.id, count(1) AS num_matches
      FROM data d
      CROSS JOIN fr
      WHERE charindex(fr.param, d.parameters) > 0
      GROUP BY id
      HAVING count(1) >= 2
    ;


    2.
    WITH f AS (
      SELECT 'PARAM1 PARAM3 PARAM7' as findstr
    )
    SELECT d.id, count(1) AS num_matches
      FROM data d
      CROSS APPLY STRING_SPLIT(d.parameters, ' ') ds
      JOIN f ON 1=1
      WHERE charindex(ds.value, f.findstr) > 0
      GROUP BY d.id
      HAVING count(1) >= 2
    ;


    см. пример на dbfiddle

    PS: относительно других СУБД все примерно так же + - , синтаксис другой может быть и наличие аналога функции STRING_SPLIT
    Ответ написан
    Комментировать
  • Как массово заполнить таблицу?

    erge
    @erge
    Примус починяю
    Если совсем все сложно с решением выше, хотя оно рабочее (пробуйте разные редакторы, выбирайте какой вам больше подойдет, читайте про регулярные выражения, я не знаю как без них вообще жить ))))

    делайте все из командной строки - скачайте утилиты командной строки sqlite - https://www.sqlite.org/download.html
    Precompiled Binaries for Windows
    sqlite-tools-win32-x86-3410000.zip
    распаковываете утилиты куда вам удобно, прописываете в переменную PATH, ну или например распакуйте в c:\bin

    копируете файл в папку с вашей бд sqlite
    далее запускаете sqlite3.exe в 'этой папке (в консоли, в командной строке!) указывая ему вашу БД, например

    sqlite3.exe my_example_db.sqlt

    далее в командной строке самой sqlite пишете
    create table ru_word (word varchar(100), freq INT);


    PS: порядок полей такой, потому что в файле такой порядок и он грузится как есть, для БД порядок не важен.
    далее

    далее указываете сеператор (разделитель полей в текстовом файле)
    .separator " "
    грузите файл в таблицу
    .import ru_50k.txt ru_word

    все!

    в итого будет примерно так (в командной строке!):
    : переходим в папку с БД, там же должен быть файлru_50k.txt
    cd C:\tmp
    
    : открываем БД в sqlite3
    c:\bin\sqlite3.exe my_example_db.sqlt
    SQLite version 3.41.0 2023-02-21 18:09:37
    Enter ".help" for usage hints.
    sqlite> create table ru_word (word varchar(100), freq INT);
    sqlite> .tables
    ru_word
    sqlite> .separator " "
    sqlite> .import ru_50k.txt ru_word
    sqlite> SELECT count(*) FROM ru_word;
    50000
    sqlite> SELECT MAX(freq) FROM ru_word;
    3854593
    sqlite> SELECT * FROM ru_word LIMIT 10;
    я 3854593
    не 3244771
    что 2665565
    в 2212420
    и 2179689
    ты 2067418
    это 1999607
    на 1240437
    с 1128276
    он 966203
    sqlite> .quit


    PPS: научитесь пользоваться поиском, например загрузка csv в sqlite и т.п. и т.д. etc
    Ответ написан
    1 комментарий
  • Можно ли посчитать количество пар с помощью sql запроса?

    erge
    @erge
    Примус починяю
    Результат больше похож на количество дублирующихся записей, а не на количество пар, потому что по количеству пар результат будет такой:

    столбец1  столбец2  результат
    фф           123            1
    фф           456            0
    йцу          123            0


    так как все же не понятно что вам необходимо, вот несколько вариантов:

    -- количество дублирующихся записей
    SELECT столбец1, столбец2, count(*)
      FROM таблица
      GROUP BY столбец1, столбец2;
    
    -- количество ПАР!!
    SELECT столбец1, столбец2, count(*) div 2
      FROM таблица
      GROUP BY столбец1, столбец2;
    
    -- если необходимо именно как в вопросе (количество дублирующихся записей):
    SELECT t1.столбец1, t1.столбец2, cnt AS результат
      FROM таблица t1
      JOIN (
      SELECT столбец1, столбец2, count(*) cnt
      FROM таблица
      GROUP BY столбец1, столбец2) t2 ON t2.столбец1 = t1.столбец1
                                     AND t2.столбец2 = t1.столбец2
    ;
    
    -- если необходимо именно как в вопросе (КОЛИЧЕСТВО ПАР!!):
    SELECT t1.столбец1, t1.столбец2, cnt div 2 AS результат
      FROM таблица t1
      JOIN (
      SELECT столбец1, столбец2, count(*) cnt
      FROM таблица
      GROUP BY столбец1, столбец2) t2 ON t2.столбец1 = t1.столбец1
                                     AND t2.столбец2 = t1.столбец2
    ;


    см. пример на dbfiddle

    PS: т.к. вы не указали СУБД, пример написан для MySQL 8
    для SQL Server div надо заменить на обычный оператор /
    для Oracle count(*) div 2 надо заменить на CEIL(count(*) / 2)
    и должно работать.
    Ответ написан
    Комментировать
  • Можно ли удалить с помощью регулярного выражения все не UNICODE символы из колонки?

    erge
    @erge
    Примус починяю
    ну, если задача стоит почистить именно UNICODE!? это строка вида
    \u0442\u0435\u043a\u0441\u0442\u0020\u0432\u0020\u044e\u043d\u0438\u043a\u043e\u0434


    то примерно как-то так:

    поиск
    (\\u[0-9a-zA-Z]{4})(?!\\u[0-9a-zA-Z]{4}).*?(\\u[0-9a-zA-Z]{4})
    замена на
    \1\2

    см. пример на regex101

    import re
    
    regex = r"(\\u[0-9a-zA-Z]{4})(?!\\u[0-9a-zA-Z]{4}).*?(\\u[0-9a-zA-Z]{4})"
    
    test_str = ("\\u0442\\u0435\\u043a\\u0441\\u0442\\u0020\\u0432\\u0020\\u044e\\u043d\\u0438\\u043a\\u043e\\u0434\n\n"
    	"\\u0442\\u0435dsds\\n\\u043a\\u0441\\u0442das\\u0020\\u0432dsdddddd\\u0020\\u044e\\u043d\\n\\n\\n\\u0438\\u043a\\u043e\\u0434")
    
    subst = "\\1\\2"
    
    # You can manually specify the number of replacements by changing the 4th argument
    result = re.sub(regex, subst, test_str, 0)
    
    if result:
        print (result)


    см. пример python

    PS: Unicode != UTF-8 charset
    это не одно и то же.
    Ответ написан
    Комментировать
  • Как отфильтровать таблицу по столбцу значение которого входит/не входит в список значений?

    erge
    @erge
    Примус починяю
    SELECT *
      FROM [dbo].[data]
      WHERE ( @p1 = 0 AND [dbo].[data].[intField] NOT IN (0,1,2,8,9) )
         OR ( @p1 = 1 AND [dbo].[data].[intField]     IN (0,1,2,8,9) )
    Ответ написан
    Комментировать
  • Как узнать количество совпадающих значений из двух разных таблиц?

    erge
    @erge
    Примус починяю
    какая СУБД !?
    У разных СУБД свои методы/функции работы с датами, а я так понимаю у вас хранится дата+время!?
    да и синтаксис SQL тоже бывает особенный...

    если предположить что это MySQL , то использовать функцию DATE() для извлечения даты.
    PS: ну либо сами перепишете соответственно

    через INNER JOIN

    SELECT count(DISTINCT c.user_id) AS first_day_order
      FROM clients c
      INNER JOIN orders o ON c.user_id = o.user_id
      WHERE DATE(c.registered_datetime) = DATE(o.when_start)
        AND DATE(c.registered_datetime) BETWEEN '2021-09-01' AND '2021-09-30'
    ;


    или через EXISTS

    SELECT count(c.user_id) AS first_day_order
      FROM clients c
      WHERE DATE(c.registered_datetime) BETWEEN '2021-09-01' AND '2021-09-30'
        AND EXISTS (
              SELECT 1 FROM orders o
                WHERE c.user_id = o.user_id
                  AND DATE(c.registered_datetime) = DATE(o.when_start)
            )
    ;
    Ответ написан
    Комментировать
  • Как записать все запросы в одном в sql?

    erge
    @erge
    Примус починяю
    SQlite3 ??
    Методы объекта Cursor SQLite3

    cursor.executescript(sql_script)

    UPDATE:
    либо так например:

    sql_script = """
    CREATE TABLE IF NOT EXISTS information
                      (id INTEGER PRIMARY KEY AUTOINCREMENT,userid INTEGER,money INTEGER,weight INTEGER,sportmode INTEGER);
    CREATE TABLE IF NOT EXISTS task
                      (id INTEGER PRIMARY KEY AUTOINCREMENT,list TEXT, status INTEGER);
    CREATE TABLE IF NOT EXISTS what
                      (mycommands TEXT);
    CREATE TABLE IF NOT EXISTS accounts
                      (login TEXT, password TEXT, token TEXT)
    """
    
    for sql in sql_script.split(";\n"):
      cursor.execute(sql)
    Ответ написан
    Комментировать
  • Возможно ли сделать нулевой count при использовании GROUP BY?

    erge
    @erge
    Примус починяю
    1. нужна таблица - календарь, либо сгенерированный набор дат
    2. либо к календарю надо сделать left join вашей таблицы, либо к вашей таблице надо сделать right join календаря.

    SQL join в примерах с описанием

    в результате получится:

    select cal.cal_date, count(person)
      from some_table st
      right join (
      -- генерируем календарь - набор дат
        select *
          from (
            select adddate('1970-01-01',t4*10000 + t3*1000 + t2*100 + t1*10 + t0) cal_date
              from
                (select 0 t0 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t0,
                (select 0 t1 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t1,
                (select 0 t2 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t2,
                (select 0 t3 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t3,
                (select 0 t4 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t4
          ) v
          where cal_date between '2021-11-01' and '2021-11-30'
      ) cal on cal.cal_date = st.date_field
      group by cal.cal_date


    в MariaDB есть Sequence Storage Engine, но до MariaDB 10.0 , он поставлялся в виде динамической плагина, начиная с MariaDB 10.1 , движок Sequence устанавливается по умолчанию. Используя его можно генерировать список дат (календарь) следующим образом:

    SELECT '2021-11-01' + INTERVAL seq DAY FROM seq_0_to_29;


    а запрос будет соответственно:

    select cal.cal_date, count(person)
      from some_table st
      right join (
      -- генерируем календарь - набор дат
        SELECT '2021-11-01' + INTERVAL seq DAY as cal_date FROM seq_0_to_29
      ) cal on cal.cal_date = st.date_field
      group by cal.cal_date
    ;


    см. пример работы на dbfiddle.uk

    и если person добавить в группировку - пример
    Ответ написан
    Комментировать
  • Как корректно разбить строку на подстроки по разделителю на множестве строк (по датасету)?

    erge
    @erge Автор вопроса
    Примус починяю
    Необходимо использовать LATERAL (inline-представление), как посоветовал Максим Y
    Но, до версии 12С это было типа недокументированной "фичей" и чтобы ее включить необходимо выполнить:
    alter session set events '22829 trace name context forever';


    Попробовал в 11g (на dbfiddle.uk) и сработало!

    https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=3aa5...

    PS: попробовал у себя на 9i и.... тоже сработало! ))

    alter session set events '22829 trace name context forever';
    
    WITH 
      test AS (
    SELECT 'проул.' as code, 'проул.|пр-к|' as str FROM dual UNION
    SELECT 'ул.' as code, 'ул.|улица|ул-ца|' as str FROM dual UNION
    SELECT 'пер.' as code, 'пер.|переулок|' as str FROM dual UNION
    SELECT 'кв-л' as code, 'кв-л|квартал|' as str FROM dual UNION
    SELECT 'линия' as code, 'линия|' as str FROM dual UNION
    SELECT 'парк' as code, 'парк|' as str FROM dual UNION
    SELECT 'рзд' as code, 'рзд|разъезд|' as str FROM dual UNION
    SELECT 'сад' as code, 'Сад|' as str FROM dual UNION
    SELECT 'тракт' as code, 'тракт|' as str FROM dual UNION
    SELECT 'тер' as code, 'тер|территория|' as str FROM dual UNION
    SELECT 'ст' as code, 'ст|станция|' as str FROM dual UNION
    SELECT 'сл' as code, 'сл|слобода|' as str FROM dual UNION
    SELECT 'пр-кт' as code, 'пр.|проспект|пр-кт|' as str FROM dual UNION
    SELECT 'шоссе' as code, 'ш.|шоссе|' as str FROM dual UNION
    SELECT 'пл' as code, 'пл|площадь|пл-дь|' as str FROM dual UNION
    SELECT 'наб.' as code, 'наб.|набережная|наб-ая|' as str FROM dual UNION
    SELECT 'тупик' as code, 'тупик|' as str FROM dual UNION
    SELECT 'мост' as code, 'мост|' as str FROM dual UNION
    SELECT 'пр.' as code, 'проезд|пр.|' as str FROM dual UNION
    SELECT 'блв.' as code, 'блв.|бульвар|' as str FROM dual UNION
    SELECT 'мкн.' as code, 'мкн.|микрорайон|' as str FROM dual UNION
    SELECT 'пос.' as code, 'пос.|посёлок|' as str FROM dual UNION
    SELECT 'овраг' as code, 'овраг|' as str FROM dual UNION
    SELECT 'городок' as code, 'городок|' as str FROM dual
    )
    SELECT t1.code, SUBSTR(t1.str, 
                  DECODE(t2.lvl, 1, 1, INSTR(t1.str, '|', 1, t2.lvl - 1) + 1),
                  INSTR(t1.str, '|', 1, t2.lvl) 
                  - DECODE(t2.lvl, 1, 1, INSTR(t1.str, '|', 1, t2.lvl - 1) + 1))
    FROM test t1,
      LATERAL (SELECT level AS lvl FROM dual
             CONNECT BY NVL(INSTR(t1.str, '|', 1, level), 0) > 0) t2
    ;


    так же есть еще вариант, через преобразование в XML:
    WITH
    str_csv AS (
      SELECT 'проул.' as code, 'проул.|пр-к|' as str FROM dual UNION
      SELECT 'ул.' as code, 'ул.|улица|ул-ца|' as str FROM dual UNION
      SELECT 'пер.' as code, 'пер.|переулок|' as str FROM dual UNION
      SELECT 'кв-л' as code, 'кв-л|квартал|' as str FROM dual UNION
      SELECT 'линия' as code, 'линия|' as str FROM dual UNION
      SELECT 'парк' as code, 'парк|' as str FROM dual UNION
      SELECT 'рзд' as code, 'рзд|разъезд|' as str FROM dual UNION
      SELECT 'сад' as code, 'Сад|' as str FROM dual UNION
      SELECT 'тракт' as code, 'тракт|' as str FROM dual UNION
      SELECT 'тер' as code, 'тер|территория|' as str FROM dual UNION
      SELECT 'ст' as code, 'ст|станция|' as str FROM dual UNION
      SELECT 'сл' as code, 'сл|слобода|' as str FROM dual UNION
      SELECT 'пр-кт' as code, 'пр.|проспект|пр-кт|' as str FROM dual UNION
      SELECT 'шоссе' as code, 'ш.|шоссе|' as str FROM dual UNION
      SELECT 'пл' as code, 'пл|площадь|пл-дь|' as str FROM dual UNION
      SELECT 'наб.' as code, 'наб.|набережная|наб-ая|' as str FROM dual UNION
      SELECT 'тупик' as code, 'тупик|' as str FROM dual UNION
      SELECT 'мост' as code, 'мост|' as str FROM dual UNION
      SELECT 'пр.' as code, 'проезд|пр.|' as str FROM dual UNION
      SELECT 'блв.' as code, 'блв.|бульвар|' as str FROM dual UNION
      SELECT 'мкн.' as code, 'мкн.|микрорайон|' as str FROM dual UNION
      SELECT 'пос.' as code, 'пос.|посёлок|' as str FROM dual UNION
      SELECT 'овраг' as code, 'овраг|' as str FROM dual UNION
      SELECT 'городок' as code, 'городок|' as str FROM dual
    ),
    str_xml AS (
      SELECT code, XMLType('<a><b>'||replace(str, '|','</b><b>')||'</b></a>') xml FROM str_csv
    )
    SELECT
        code, extractValue(value(t),'b') str_type
      FROM
        str_xml s,
        TABLE(XMLSequence(s.xml.extract('a/b'))) t
      WHERE extractValue(value(t),'b') is not null
    ;
    Ответ написан
    Комментировать
  • Как сделать запрос в запросе в mysql?

    erge
    @erge
    Примус починяю

    надо что бы при запросе вывел где status= true, и count_id = количество id за 30 дней.
    |id|id_2|name|status|date| count_id |


    • количество записей считается COUNT при группировке по полям (см. GROUP BY), в данном случае по интервалу дат

    • но... в таком виде
      |id|id_2|name|status|date| count_id |
      вывести не получится! т.к. группировать по полям |id|id_2|name| не имеет смысла, они могут быть уникальны и никакого COUNT за интервал не получится, например как считать количество в интервале для id=1,2,3 ... ??? это группироваться никак не будет вообще, будет выводиться построчно для каждого id и количество будет Всегда равно =1 и так для всех id. определитесь что вам надо?! конкретно

    • можно выбрать записи со статусом true и посчитать количество в интервале, для этого поле date привести в некий интервальный формат, либо если надо за ПОСЛЕДНИЕ 30 дней, то просто:
      SELECT count(id) count_id
        FROM tbl
        WHERE status = 'true'
          AND date >= now() - interval 30 day
      ;




    см. пример на dbfiddle
    Ответ написан
    Комментировать
  • Как сделать, чтобы дата отображалась количеством часов в БД?

    erge
    @erge
    Примус починяю
    если предположить, что переменная типа DATETIME, то примерно так:

    -- дата начала
    DECLARE @t_start AS DATETIME = DATEADD(minute, -7410, GETDATE());
    -- дата конца
    DECLARE @t_finish AS DATETIME = GETDATE();
    -- разница между датами начала и конца в переменной типа DATETIME
    DECLARE @t_diff AS DATETIME = @t_finish - @t_start;
    
    -- разница между датами начала и конца
    SELECT @t_diff;
    
    SELECT DATEDIFF(second, DATEFROMPARTS(1900,1,1), @t_diff) / 3600.0 AS diff_h


    см. https://dbfiddle.uk/?rdbms=sqlserver_2014&fiddle=9...
    Ответ написан
    Комментировать
  • Как построить sql запрос?

    erge
    @erge
    Примус починяю
    как-то так...

    SELECT
        c.title,
        ou.name,
        m.text,
        FROM_UNIXTIME(m.date) AS dt
      FROM chat_users cu
      INNER JOIN chat_users cuu ON cuu.chat_id = cu.chat_id AND cuu.user_id != cu.user_id
      INNER JOIN users ou ON ou.id = cuu.user_id
      INNER JOIN chat c ON c.id = cu.chat_id
      INNER JOIN messages m ON m.user_id = cuu.user_id AND m.chat_id = cu.chat_id
      WHERE cu.user_id = :ID_USER  -- ID пользователя по которому выбирать чаты.
      ORDER BY c.title ASC, m.date DESC
    Ответ написан
    Комментировать
  • Как найти ошибку sql из лога MODX?

    erge
    @erge
    Примус починяю
    Откройте файл /home/site.ru/core/xpdo/om/xpdoobject.class.php строка 240
    и посмотрите что там за запрос такой, который ошибку выдает.
    хотя это наврено PDO шный класс? хм... ну хотя бы посмотреть какой там объект/метод вызывается
    и в коде искать вызов этого места.

    PS: скопируйте с продакшена базу! тогда возможно скорее всего и получится повторить.
    Ответ написан
  • Почему не работает изменение таблицы?

    erge
    @erge
    Примус починяю
    Melkij , дело говорит )
    см. PostgreSQL CHECK Constraint

    ALTER TABLE persons 
       ADD CONSTRAINT persons_check_rols CHECK (rols in('registrator', 'coordinator', 'user'));
    Ответ написан
    Комментировать
  • Как следует изменить запрос чтобы при выборке всех записей подзапрос возвращал по одному значению для каждого кортежа?

    erge
    @erge
    Примус починяю
    Подзапрос который вставляется в список колонок должен возрващать только ОДНУ строку.
    либо перепишите подзапрос, чтобы он в любом случае возвращал только одну строку, либо джойните его или таблицу.
    Кроме того этот подзапрос никак не привязан к таблицам выборки ?? так и задуманно?

    какая вообще связь между таблицами, что это за таблицы? какой должен быть результат выборки?

    Вангую, что должно быть примерно так:

    SELECT
         w.Id
        ,w.IMO
        ,v.Name
        ,w.loginManager
        ,um.Name AS managerName
        ,w.loginStorekeeper
        ,umk.Name AS storekeeperName
        ,w.Date 
      FROM Waybill w
      INNER JOIN Vessel v ON w.IMO = v.IMO
      INNER JOIN User um  ON w.loginManager = um.Login
      INNER JOIN User umk ON w.loginStorekeeper = umk.Login
      ORDER BY w.Id
    Ответ написан
    1 комментарий
  • Избыточные данные или сложная логика запроса?

    erge
    @erge
    Примус починяю
    Одни и те же вопросы с разных аккаунтов??

    я так понимаю что это тоже самое или суть аналогична: Получить строку с максимальным совпадением? ??
    вместо `movie_desc` - `setting_value` (смотри ниже запрос и примеры)

    через оконные функции надо делать, если на MySQL 8 (СУБД вы НЕ указали...), функция ранжирования - row_number()

    -- здесь я вынес параметры (домены, языки) в отдельное представление param,
    -- которое определяется перед SELECT
    -- это сделано, для того чтобы по всему запросу не искать и вписывать их
    -- меняется все в одном месте:
    WITH param AS (
      SELECT
          2 AS primary_domain_id,    -- id первичного домена
          1 AS secondary_domain_id,  -- id вторичного домена
          2 AS primary_language_id,  -- id первичного языка
          1 AS secondary_language_id -- id вторичного языка
        FROM dual
    )
    SELECT *
      FROM (
        SELECT m.*,
            row_number() over (
              partition by m.movie_id
              order by
              	case
              	  when m.domain_id = p.primary_domain_id then 100
              	  when m.domain_id = p.secondary_domain_id then 50
              	  else 1
                end DESC,
              	case
              	  when m.language_id = p.primary_language_id then 100
              	  when m.language_id = p.secondary_language_id then 50
              	  else 1
                end DESC
            ) rn
          FROM `movie_desc` m, param p
          WHERE (m.domain_id = p.primary_domain_id
              OR m.domain_id = p.secondary_domain_id
              OR m.domain_id IS NULL)
    	    AND (m.language_id = p.primary_language_id
              OR m.language_id = p.secondary_language_id
              OR m.language_id IS NULL)
      ) t
      WHERE t.rn = 1
    ;


    Примеры на:
    https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=f46bf1...
    https://www.db-fiddle.com/f/8UigbxU6uNg6guU8ygKgrA/1

    PS: если MySQL более древний чем 8й, то попробуйте переписать как описано на второй странице той же статьи , ссылка на которую приведена выше.
    www.sql-tutorial.ru/ru/book_row_number_function/pa...
    Ответ написан
    2 комментария
  • Как вытащить данные при вложенном запросе?

    erge
    @erge
    Примус починяю
    У вас таблица oc_product внутри подзапроса, поэтому сначала нужно вывести там, а уже потом "сверху":

    SELECT
        name,
        sku,
        CONCAT('https://домен/', IF(ua2.keyword IS NULL,'',CONCAT(ua2.keyword, '/')), IF(ua3.keyword IS NULL,'',CONCAT(ua3.keyword, '/')), IF(ua4.keyword IS NULL,'',CONCAT(ua4.keyword, '/')), ua1.keyword) AS url
      FROM (
        SELECT
            name,
            p.sku,
            CONCAT( 'product_id=', p.product_id ) AS product_query,
            CONCAT( 'category_id=', pc.category_id ) AS category_query,
            CONCAT( 'series_id=', ps.series_id ) AS series_query,
            CONCAT( 'subcategory_id=', psc.subcategory_id ) AS subcategory_query
          FROM `oc_product_description` pd
          LEFT JOIN oc_product p ON (p.product_id=pd.product_id)
          LEFT JOIN oc_product_to_category pc ON (pc.product_id=p.product_id)
          LEFT JOIN oc_product_to_series ps ON (ps.product_id=p.product_id)
          LEFT JOIN oc_product_to_subcategory psc ON (psc.product_id=p.product_id)
          WHERE p.date_available <= NOW()
            AND p.status = '1'
      ) pd
      LEFT JOIN oc_url_alias ua1 ON ( pd.`product_query` = ua1.`query` )
      LEFT JOIN oc_url_alias ua2 ON ( pd.`category_query` = ua2.`query` )
      LEFT JOIN oc_url_alias ua3 ON ( pd.`series_query` = ua3.`query` )
      LEFT JOIN oc_url_alias ua4 ON ( pd.`subcategory_query` = ua4.`query` )
    ;


    PS: и форматируйте запросы нормально, читать будет удобнее.
    Ответ написан
    Комментировать