Какое логическое значение возвращает целое число или строку переменной - PullRequest
0 голосов
/ 14 июня 2019

Я использую пользовательские переменные для эмуляции

ROW_NUMBER() OVER (PARTITION BY `wsf_ref`, `type` ORDER BY `wsf_value` DESC)

Обратите внимание на переменную @type.Я установил его на a, чтобы прояснить проблему, но сначала была пустая строка.

CROSS JOIN ( SELECT @rn := 0, @type := 'a', @ref := '') as var

SQL DEMO # 1

CREATE TABLE t (
  `id` INTEGER,
  `wsf_ref` INTEGER,
  `status` VARCHAR(8),
  `type` VARCHAR(6),
  `wsf_progress` VARCHAR(5),
  `wsf_value` INTEGER
);

SELECT t.*, @rn := if(  @ref = `wsf_ref`,
                       if ( @type = `type`, 
                             @rn + 1,
                             if( @type := `type`, 1, 1)                     
                           ),
                       if ( (@ref := `wsf_ref`) and (@type := `type`), 1, 1)
                    ) as rn,
            @type,
            @ref
FROM t
CROSS JOIN ( SELECT @rn := 0, @type := 'a', @ref := '') as var
ORDER BY `wsf_ref`, `type`, `wsf_value` DESC;

Вы видите, как первая строка вводит последнее условие и устанавливает обе переменные правильно:

ВЫХОД

| id | wsf_ref |   status |   type | wsf_progress | wsf_value | rn |  @type | @ref |
|----|---------|----------|--------|--------------|-----------|----|--------|------|
|  6 |       1 | Approved |   blue |        Day 1 |        25 |  1 |   blue |    1 |
|  5 |       1 | Approved |   blue |        Day 1 |        10 |  2 |   blue |    1 |
|  3 |       1 | Approved | orange |        Day 1 |        20 |  1 | orange |    1 |

Buf, если wsf_ref равно VARCHAR я получил другой результат

SQL DEMO # 2

CREATE TABLE t (
  `id` INTEGER,
  `wsf_ref` VARCHAR(255),
  `status` VARCHAR(255),
  `type` VARCHAR(255),
  `wsf_progress` VARCHAR(5),
  `wsf_value` INTEGER
);

Здесь вы можете увидеть первую строку, переменная @type не установленаи до сих пор a

ВЫХОД

| id |  wsf_ref |   status |   type | wsf_progress | wsf_value | rn |  @type |     @ref |
|----|----------|----------|--------|--------------|-----------|----|--------|----------|
|  3 | WSF19-01 | Approved |  Perch |        Day 2 |        20 |  1 |      a | WSF19-01 |
|  4 | WSF19-01 | Approved |  Perch |        Day 2 |        10 |  1 |  Perch | WSF19-01 |

После некоторой отладки я обнаружил, что проблема с последним назначением

if ( (@ref := `wsf_ref`) and (@type := `type`), 1, 1)

Вкл.В первом случае, когда wsf_ref является целым числом, присваивание оценивается как истинное, а затем проверяется и второе условие.Во втором случае, когда wsf_ref является строкой, результат ложен, а второе условие игнорируется.

Я изменяю условие на:

if ( (@ref := `wsf_ref`) OR (@type := `type`), 1, 1)

Так что даже если первое условие ложновсе еще попробуйте оценить второе условие, и теперь оба запроса работают нормально.

Так зачем назначать @ref число для получения логического значения, отличного от назначения строки?

1 Ответ

1 голос
/ 14 июня 2019

Ваше выражение:

if ( (@ref := `wsf_ref`) and (@type := `type`), 1, 1)

MySQL не обязательно оценивает оба условия.Нужно только оценить «второй», если «первый» оценивается как истинный.(Я помещаю «first» и «second» в кавычки, потому что порядок вычисления не определен, но идея одинакова независимо.)

Когда это строки, результатом @ref := wsf_rf является строка,Строка преобразуется в логическое значение через число.Значение равно 0, что ложно, если только строка не начинается с цифры.

Следовательно, оба условия не оцениваются и второе не присваивается.

Я бызапишите это как:

SELECT t.*,
       (@rn := if(@tr = CONCAT_WS(':', wsf_ref, type),
                  @rn + 1,
                  if(@tr := CONCAT_WS(':', wsf_ref, type), 1, 1
                    )                     
                 )
       ) as rn
FROM (SELECT t.*
      FROM t 
      ORDER BY `wsf_ref`, `type`, `wsf_value` DESC
     ) t CROSS JOIN
     (SELECT @rn := 0, @tr := '') params;

Я переместил ORDER BY в подзапрос, потому что более поздние версии MySQL не очень хорошо обрабатывают ORDER BY и переменные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...