Nano Hash - криптовалюты, майнинг, программирование

Функция SQLite RANDOM() в CTE

Я обнаружил неправильное поведение функции RANDOM() в SQLite.

Я хочу генерировать случайные группы, используя random RANDOM() и CASE. Однако похоже, что CTE ведет себя некорректно.

Ожидание против реальности

Сначала создадим таблицу

DROP TABLE IF EXISTS tt10ROWS;
CREATE TEMP TABLE tt10ROWS (
    some_int INTEGER);

INSERT INTO tt10ROWS VALUES
    (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
SELECT * FROM tt10ROWS;

Таблица №1

Неправильное поведение

WITH 
    -- 2.a add columns with random number and save in CTE
    STEP_01 AS (
        SELECT
            *,
            ABS(RANDOM()) % 4 + 1 AS RAND_1_TO_4
        FROM tt10ROWS)
        
    -- 2.b - get random group
select
    *,
    CASE 
        WHEN RAND_1_TO_4 = 1 THEN 'GROUP_01'
        WHEN RAND_1_TO_4 = 2 THEN 'GROUP_02'
        WHEN RAND_1_TO_4 = 3 THEN 'GROUP_03'
        WHEN RAND_1_TO_4 = 4 THEN 'GROUP_04' 
        END AS GROUP_IT
from STEP_01;

Используя такой запрос, мы получаем таблицу, которая генерирует правильные значения для столбцов RAND

DROP TABLE IF EXISTS tt10ROWS;
CREATE TEMP TABLE tt10ROWS (
    some_int INTEGER);

INSERT INTO tt10ROWS VALUES
    (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
SELECT * FROM tt10ROWS;
TO_4, но столбец GROUP_IT неверен. Мы видим, что группы не совпадают, а некоторые группы даже отсутствуют.

Правильное поведение

Я нашел обходной путь для такой проблемы, создав временную таблицу вместо использования CTE. Это помогло.

-- 1.a - add column with random number 1-4 and save as TEMP TABLE
drop table if exists ttSTEP01;
CREATE TEMP TABLE ttSTEP01 AS
        SELECT
            *,
            ABS(RANDOM()) % 4 + 1 AS RAND_1_TO_4
        FROM tt10ROWS;

-- 1.b - get random group
select
    *,
    CASE 
        WHEN RAND_1_TO_4 = 1 THEN 'GROUP_01'
        WHEN RAND_1_TO_4 = 2 THEN 'GROUP_02'
        WHEN RAND_1_TO_4 = 3 THEN 'GROUP_03'
        WHEN RAND_1_TO_4 = 4 THEN 'GROUP_04' 
        END AS GROUP_IT
from ttSTEP01;

ВОПРОС

Каковы причины такого поведения, когда столбец GROUP_IT не генерируется должным образом?


Ответы:


1

Если вы посмотрите на байт-код, сгенерированный неверным запросом с использованием EXPLAIN, вы увидите, что каждый при ссылке на столбец RAND_1_TO_4 его значение пересчитывается и используется новое случайное число (я подозреваю, но не уверен на 100%, что это как-то связано с тем, что random() является недетерминированной функцией). Нулевые значения предназначены для тех случаев, когда ни один из тестов CASE не оказывается верным.

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

13.10.2020
  • Нулевые значения предназначены для тех случаев, когда ни один из тестов CASE не оказывается истинным, если RAND_1_TO_4 пересчитывается каждый раз, когда на него ссылаются (что, по-видимому, имеет место здесь), оно должно пересчитывается как ABS(RANDOM()) % 4 + 1, поэтому в результате не должно быть null. Поскольку есть null, это означает, что пересчет не выполняется так, как должен. Это пахнет ошибкой. 13.10.2020
  • @forpas Предположим, что в итоге получается 4 = 1, 3 = 2, 2 = 3, 1 = 4. Все они ложны, и, поскольку в конце нет одеяла, case возвращает null. 14.10.2020
  • Также см. эту старую ветку 2008 года. Мнения о том, является ли это ошибкой, разделились, и я подозреваю, что drh зарегистрировал ее как Wontfix. 14.10.2020
  • Вы правы насчет нулей, и просто изменив синтаксис CASE так, чтобы RAND_1_TO_4 упоминался только один раз, нули удаляются: ="nofollow noreferrer">dbfiddle.uk/ 14.10.2020
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..


    © 2024 nano-hash.ru, Nano Hash - криптовалюты, майнинг, программирование