返回的布尔值将整数或字符串分配给变量

时间:2019-06-14 01:09:52

标签: mysql sql if-statement user-variables

我正在使用用户变量进行仿真

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 |

如果wsf_refVARCHAR,我得到了不同的结果

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为整数时,赋值评估为true,然后还要检查第二种条件。在第二种情况下,当wsf_ref为字符串时,结果为false,第二个条件被忽略。

我将条件更改为:

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

因此,即使第一个条件为假,仍然尝试评估第二个条件,现在两个查询都可以正常工作。

那么,为什么给@ref分配一个数字而不是分配一个字符串来得到一个布尔值?

1 个答案:

答案 0 :(得分:1)

您的表情是:

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

MySQL不必同时评估这两种情况。如果“第一个”的评估结果为true,则仅需要评估“第二个”。 (我将“第一”和“第二”用引号引起来,因为没有确定评估顺序,但是无论如何,想法都是相同的。)

当这些是字符串时,@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和变量。