【问题标题】:What boolean value return assign integer or string to a variable什么布尔值返回将整数或字符串分配给变量
【发布时间】:2019-06-14 01:09:52
【问题描述】:

我使用用户变量来模拟

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

我将条件改为:

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

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

那么为什么分配 @ref 一个数字会得到与分配一个字符串不同的布尔值呢?

【问题讨论】:

  • 在同一个 select 语句中读取和分配变量在 MySQL 中是未定义的——请参阅手册重新变量和分配。涉及 CASE 的某些表达式适用于某些实现,但这并不能保证行为。 (我没有链接。)

标签: mysql sql if-statement user-variables


【解决方案1】:

你的表达是:

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

MySQL 不一定同时评估这两个条件。如果“第一个”评估为真,它只需要评估“第二个”。 (我将“第一”和“第二”放在引号中,因为评估的顺序没有确定,但想法是一样的。)

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

【讨论】:

  • 我明白了。我想是这样的,但在我看来,如果不是 0 那么应该是真的。不知道字符串变成 0。CONCAT 的技巧很棒,花了我很多工作来处理那些嵌套的 IF 谢谢
猜你喜欢
  • 2020-01-17
  • 2023-03-20
  • 2019-02-25
  • 1970-01-01
  • 2018-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-29
相关资源
最近更新 更多