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

    @Miron11
    Пишу sql 20 лет. Срок :)
    У Вас 2 варианта,
    1. использовать отфильтрованный список servers_world
    2 использовать значение typew в контексте выборки ( так же с фильтром )
    1-й подход может, в свою очередь, иметь два подхода, в зависимости от того, какие фишки SQL поддерживает Ваша СУБД.

    1. C(ommon) T(able) E(xpression):

    WITH filtered_servers_world AS (
    SELECT DISTINCT cat_id, typew
    FROM filtered_servers_world
    )
    SELECT `servers_texts`.*
    , `filtered_servers_world`.`typew`
    FROM `servers_texts`
    LEFT JOIN `filtered_servers_world` ON `servers_texts`.`id` = `filtered_servers_world`.`cat_id`
    WHERE `servers_texts`.`premod` = 1
    AND `servers_texts`.`cat_id` = ' 10'
    AND `filtered_servers_world`.`typew` = ' 1'
    ORDER BY `vote` DESC, `servers_texts`.`id` DESC

    2. Sub-Query с алиасом:
    SELECT `servers_texts`.*
    , `filtered_servers_world`.`typew`
    FROM `servers_texts`
    LEFT JOIN (SELECT DISTINCT cat_id
    , typew
    FROM `servers_world`) AS `filtered_servers_world`
    ON `servers_texts`.`id` = `filtered_servers_world`.`cat_id`
    WHERE `servers_texts`.`premod` = 1
    AND `servers_texts`.`cat_id` = ' 10'
    AND `filtered_servers_world`.`typew` = ' 1'
    ORDER BY `vote` DESC, `servers_texts`.`id` DESC

    3. inline используя контекст выборки данных, менее эффективно, но иногда работает лучше подходов 1, 2 в частности, когда СУБД распределенная, поскольку уменьшает количество раз данные копируются между порциями данных разделенных на разные машины

    SELECT *
    FROM (
    SELECT `servers_texts`.*
    , (SELECT MAX(`servers_world`.`typew`) FROM `servers_world` WHERE `servers_world`.`cat_id` = `servers_texts` .`cat_id`) AS `typew`
    FROM `servers_texts`
    WHERE `servers_texts`.`premod` = 1
    AND `servers_texts`.`cat_id` = ' 10'
    ) AS `dt`
    WHERE `typew` = '1'
    AND `premod` = 1
    AND `cat_id` = ' 10'
    ORDER BY `vote` DESC, `servers_texts`.`id` DESC

    4 lateral join или outer apply

    SELECT `servers_texts`.*
    , `filtered_servers_world`.`typew`
    FROM `servers_texts`
    LEFT JOIN LATERAL (
    SELECT `typew`
    FROM `servers_world`
    WHERE `servers_world`.`cat_id` = `servers_texts`.`cat_id`
    ORDER BY `typew` DESC
    LIMIT 1
    ) `filtered_servers_world` ON TRUE
    WHERE `servers_texts`.`premod` = 1
    AND `servers_texts`.`cat_id` = ' 10'
    AND `filtered_servers_world`.`typew` = ' 1'
    ORDER BY `vote` DESC, `servers_texts`.`id` DESC

    Заметьте, я поменял поле на котором servers_texts и servers_world установили родство. В Вашем оригинальном запросе поле servers_texts использует id в JOIN выражении, но глядя на поля предложенные в таблицах cat_id выглядит, как поле, которое больше подходит.
    Возможно я не прав, пожалуйста проверьте.
    В крайнем случае, пожалуйста верните оригинальное поле.

    -- Удачи
    Ответ написан
  • Как определить, в какой ситуации оптимальнее использовать подзапросы, а не соединения?

    @Miron11
    Пишу sql 20 лет. Срок :)
    1. подзапросы типа exists лучше для
    • распределенных баз
    • минимизации ресурса памяти и уменьшения или изъятия параллелизма

    2. join лучше для
    • локальной базы
    • концентрации ресурсов на выполнении запроса

    3. outer apply / lateral join позволяют использовать преимущества correlated subqueries и выбирать данные, существенные преимущества
    • минимизируются изменения логики выборки данных
    • часто удается вовлечь индексы в выборку, не обращая внимание на распределение данных внутри домена, когда рост количества таблиц вовлеченных в inner / outer join с различными срезами данных, ведет к отказу оптимизатора запросов использовать индексы
    Ответ написан
    Комментировать
  • Почему у меня под конец в листе rows начинают хранится одни и те же значения?

    @Miron11
    Пишу sql 20 лет. Срок :)
    Есть два подхода, чтобы справиться, перенести линию кода
    string[] row = new string[rd.FieldCount];
    сюда
    while (rd.Read())
    {

    сразу после фигурной скобки, или изменить линию кода
    rows.Add(row.Clone());
    Причина, array это "reference type", познакомиться с описание reference type можно здесь, ключ к пониманию следующий абзац:
    With reference types, two variables can reference the same object; therefore, operations on one variable can affect the object referenced by the other variable.
    . Точнее, что такое reference type потребует отладчик и работу с MSIL. Вот как описывает reference type MSIL standard:

    I.8.2.1 Value types and reference types
    There are two kinds of types: value types and reference types.
    [...]
     Reference types –A value described by a reference type denotes the location of another
    value.
    По этой причине, не смотря на то, что вы трижды сместили строку в DataReader, запись каждый раз производилась в один и тот же блок данных, переписывая его, а три записи в неизвестной лист были обращены к одному и тому же блоку.
    Ответ написан
    Комментировать
  • Как сделать min() по join таблице в построителе запросов?

    @Miron11
    Пишу sql 20 лет. Срок :)
    SQL
    ---
    select department.*
             , coalesce(dptSlr.minSalary, 0.00) as minSalary
    FROM `department` 
    left outer join 
    (SELECT employee.departmentId, MIN(employee.salary ) AS minSalary 
        FROM employee
        GROUP BY employee.departmentId) dptSlr
    on department.id = dptSlr.departmentId;
    Ответ написан
    Комментировать
  • Почему SQL запрос неправильный?

    @Miron11
    Пишу sql 20 лет. Срок :)
    select good, amount as sum from Payments
    order by sum desc;
    Ответ написан
    Комментировать
  • Как в Elasticsearch проверить, что массив содержит определенное количество значений?

    @Miron11
    Пишу sql 20 лет. Срок :)
    Did you try this approach, adjusting to field names.
    Passed test on ES 8.2.2:
    {
      "aggs" : {
        "@timestamp": {
          "terms" : { "field" : "@timestamp"},   
    
      "aggs": {
        "shift_count": {
          "value_count": { "field": "shifts.id" }
        },
        "shift_count_filter": {
          "bucket_selector": {
            "buckets_path": {
              "shiftCount": "shift_count"
            },
            "script": "params.shiftCount > 1"
          }
        }
      }}}
    }

    I am still searching how to apply filter over aggregate using "filtered" query approach, something like
    select * from ( select count(*) as count_of_items, item_name from item_collection group by item_name ) as inner_query 
    where count_of_items > 1

    as this approach, using aggregates feels more like a workaround ( thought robust to use in production ).
    If you come over something interesting, please post here.
    ---
    I don't know the reason as to why, since I just installed elasticsearch to investigate your question, the approach with measuring array using property values and function size() didn't work.
    Based on all I have learned so far, the dynamic property, currently set to false on the shifts field may need to be modified to false, to enable dynamic scripting.
    For aggregate approach above to work over nested field with text sub - field, the field may need to be applied with "fielddata" attribute set to true, by default if is false on such fields. It could be this is a new behavior since version 8.2.2. Here is error message I was getting in some experiments
    "type" : "illegal_argument_exception",
    "reason" : "Text fields are not optimised for operations that require per-document field data like aggregations and sorting, so these operations are disabled by default. Please use a keyword field instead. Alternatively, set fielddata=true on [...] in order to load field data by uninverting the inverted index. Note that this can use significant memory."
    here is script to apply fielddata attribute:
    shifts: {
      type: 'object',
      dynamic: false,
      fielddata: true,
      properties: { id: { type: 'keyword' }, { type: 'keyword' } },
    }

    -- cheers
    Ответ написан
    Комментировать
  • Что это за конструкция?

    @Miron11
    Пишу sql 20 лет. Срок :)
    Обычно в SQL это пишут, чтобы не забыть проверить какие - то условия, когда появляются ошибки. Никто не объясняет эти вещи в комментариях. Процедуры, обычно, длинные, и каждая лишняя строчка, это не позволительная роскошь.
    Иногда это результат спешки, тогда надо покопаться, и если все верно, убрать лишние шаги. Да, некоторые программисты пишут такой код, в качестве флажка, чтобы напомнить себе, что что - то надо доводить до ума.
    Ответ написан
    Комментировать
  • Как в Вывести обединение таблиц по условию ??

    @Miron11
    Пишу sql 20 лет. Срок :)
    Книга без автора?
    Код книги в списке авторов?
    Если первое ещё возможно, если запись утеряна, то второе, это скорее пережиток ручной учетной записи, которую не стоит мучать в СУБД.
    Может не так элегантно, но понятнее сделать UNION
    1. select ..., min(author_id) from books inner join authors on books.author_id = authors.author_id
    group by ...
    2. select ..., 'empty' as author_id from books where not exists ( select 1 from authors where author_id = books.author_id)
    и представить их
    1 union 2
    -- CTE прекрасно работают с union, их надо вынести в предъём выражения.
    -- Если у авторов есть взаимоотношения родитель - ребенок, то эти взаимоотношения и отслеживаются в CTE, там же задается указатель уровня, по которому можно выбрать старшую запись в выборке ( where parent_level = 1 )
    Ответ написан
    Комментировать
  • Как правильно составить SQL запрос?

    @Miron11
    Пишу sql 20 лет. Срок :)
    select count(*) from (select game, game_id from bets group by game, game_id) as dt
    Ответ написан
    Комментировать
  • Как скопировать представление?

    @Miron11
    Пишу sql 20 лет. Срок :)
    Иногда view создают в какое - то время, а потом база меняется.
    И так view может и есть, но не работает.
    Их можно игнорировать.
    Если базы на самом деле одинаковые, это одно из таких устаревших view, которое не построится и на той базе, из которой Вы его оригинально взяли.
    Возможно есть другие причины... поделитесь копией ошибки и, если имеет смысл, строкой, которая её вызывает.
    Ответ написан
    Комментировать
  • Запрет на редактирование строки в Mysql по ID?

    @Miron11
    Пишу sql 20 лет. Срок :)
    снимите привилегии пользователей, которые сейчас созданы в базе данных. Оставьте им право читать. Особое внимание уделите административным учетным записям, например root. В моей практике мне не приходилось защищать конкретно MySQL, поэтому я не знаю, можно ли изменить имя пользователя root, если можно, сделайте это, конечно же изменив его пароль.
    Сделайте специальный логин, которому присвоено разрешение изменять данные. Запомните пароль этого пользователя и сложите его в сейф. Ключ от сейфа повесьте на шею и никому не давайте.
    Сделайте так, чтобы вход с паролем этого пользователя имел отдельный доступ к базе данных. Чтобы его не надо было выводить где - то в конфигурации программы, обеспечивающей работу сайта. Входите в этот счет с паролем через защищенное приложение так, чтобы никто не смог ни увидеть ваш пароль, ни считать его через какие - то устройства, в частности тех, которые слушают что передается по сети. В принципе все современные программы, которые приходят с продуктом защищают пароль логина. Но детали могут быть существенны, прочтите документацию, если есть сомнения. Там как правило описывается хорошо ли защищен сам процесс присоединения к базе данных тем или иным устройством.
    Ну и наконец, защитите таким же подходом машину на которой установлена база данных и сайт.
    В конце - концов, если с первой попытки не получится, и кто - то продолжит "безобразничать", повторите цикл, только теперь уже с некоторым опытом прежней тренировки.
    По мере работы над этой областью рано или поздно Вы столкнетесь с тем, что либо человек, либо какой - то процесс установленный либо на машине, либо в самом приложении сайта, выполняет подмену указателей адресов, либо заметив этот процесс и сличив временные метки записей - их изменений, либо заметив, что кто - то присоединился к базе данных без разрешения с высоко привилегированным пользователем. Обнаружить это можно так же установив триггеры на таблицах, фиксирующие изменения, включая время записи имя учетной записи и значение поля до изменения и после. Проблема в том, что Ваша база в данный момент эксплуатируется не по назначению неким третьим лицом, и это лицо может исказить и эти трассировочные записи, поэтому на начальном этапе необходимо все - таки изолировать пользовательские записи и засекретить вход имеющий привилегии менять данные и административно распоряжаться ресурсами.
    Ответ написан
    4 комментария
  • Как запихнуть все столбцы из JOIN в один столбец?

    @Miron11
    Пишу sql 20 лет. Срок :)
    Не пробовали поискать в яндексе?
    Я ввел запрос "MySQL for json" выражение "for json" поддерживается в SQL Server и это считается золотой стандарт СУБД, поэтому похожие функции в других СУБД можно искать по ключевым словам.
    Вот ответ, по - моему подходит.
    https://stackoverflow.com/questions/41758870/how-t...
    Ответ написан
    Комментировать
  • Как сделать поиск по регулярному выражению SQL?

    @Miron11
    Пишу sql 20 лет. Срок :)
    У Вас есть 2 основных подхода
    1. через 2 выражения пользуясь операторами перечисленными здесь
    https://dev.mysql.com/doc/refman/8.0/en/regexp.html
    Возможно не всеми в любой комбинации, но существенно то, что один оператор должен найти часть последовательности символов, которые должны ответить, например
    SELECT *
    FROM `post`
    WHERE
    -- 1-е выражение
    `description` LIKE 'itemid=34543%'
    -- 2-е выражение
    AND
    `description` NOT RLIKE 'itemid=34543[0-9]+'

    2. через 1 регулярное выражение, очень похожее на то, которое Вы предложили, но видимо с \ ( backslash ) символом проведенным дважды, на той же странице объясняется почему: "Because MySQL uses the C escape syntax in strings (for example, \n to represent the newline character), you must double any \ that you use in your expr and pat arguments."
    Если по той или иной причине выражение артачится, наверное можно воспользоваться выражением на один символ длиннее, для выражения цифр [^0-9]
    Ну и наверное надо воспользоваться плюсом, а не звездочкой справа [^0-9]+, иначе эта часть становится не обязательной, и запрос может выбрать, например, значение 'itemid=34543'
    ---
    Всего хорошего!
    Ответ написан
    Комментировать
  • Почему долго выполняется sql запрос?

    @Miron11
    Пишу sql 20 лет. Срок :)
    Если Вам нужен очень быстрый ответ, разбиваете имена городов на буквы, создаёте XML индекс, и выбираете имена городов во временную таблицу после чего заканчиваете запрос по ключу города. В Постгрес столько расширений что я почти уверен, вы найдете все ответы за несколько запросов в Яндексе.
    Ответ написан
    Комментировать