what boolean value return 赋整数或字符串给变量
What boolean value return assign integer or string to a variable
我正在使用用户变量来模拟
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
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
我得到不同的结果
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
数字得到的布尔值与分配字符串不同?
你的表达是:
if ( (@ref := `wsf_ref`) and (@type := `type`), 1, 1)
MySQL 不一定评估这两个条件。如果 "first" 的计算结果为真,它只需要计算 "second" 一个。 (我把 "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
和变量。
我正在使用用户变量来模拟
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
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
我得到不同的结果
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
数字得到的布尔值与分配字符串不同?
你的表达是:
if ( (@ref := `wsf_ref`) and (@type := `type`), 1, 1)
MySQL 不一定评估这两个条件。如果 "first" 的计算结果为真,它只需要计算 "second" 一个。 (我把 "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
和变量。