LEFT 用于子查询
LEFT used in subquery
我的问题很简单。下面查询returns错误:
Mensagem 537, Level 16, state 2, Line 1
Invalid length parameter passed to the LEFT or SUBSTRING function..
代码:
Select
c.name "Nome Conta",
c.code "Código Conta",
sq1.[Nome Conta] Tipo
From
(chart_tag ct inner join chart c on ct.id_chart = c.id_chart) inner join
(Select
c1.name "Nome Conta",
LEFT(c1.code, (charindex('00', c1.code)-1)) "Código Conta"
from chart_tag ct1 inner join chart c1 on ct1.id_chart = c1.id_chart
where ct1.id_tag = 18159 and
c1.id_type_chart = 1942 and
c1.only_accrual = 1 and
c1.code not in ('99', '98')) sq1 on LEFT(c.code, 1) = sq1.[Código Conta]
Where
ct.id_tag = 18159 and
c.id_type_chart = 1942 and
c.only_accrual = 0
order by
c.code
第一个内连接returns以下table:
Name
Code
Caixa Geral
1111001
Caixa Departamentos/Operador
1111005
Valores Recebidos a Depositar
1111025
Bancos Conta Movimento
1112001
Bancos Conta Movimento - Vincul
1112005
Bancos Conta Subvenções
1112021
Bancos Conta Doações
1112022
Bancos Conta Contribuições
1112023
Aplicações Financeiras Imediata
1113001
Aplicações Financeiras Vinc.
1113005
单独执行From子查询没有返回错误。生成如下table:
Name
code
ATIVO
1
ATIVO CIRCULANTE
11
CAIXA E EQUIVALENTES
111
CAIXA
1111
BANCOS
1112
APLICAÇÕES FINANCEIRAS
1113
来自
Name
code
ATIVO
1000000
ATIVO CIRCULANTE
1100000
CAIXA E EQUIVALENTES
1110000
CAIXA
1111000
BANCOS
1112000
APLICAÇÕES FINANCEIRAS
1113000
子查询:
Select
c1.name "Nome Conta",
LEFT(c1.code, (charindex('00', c1.code)-1)) "Código Conta"
from
chart_tag ct1 inner join chart c1 on ct1.id_chart = c1.id_chart
where
ct1.id_tag = 18159 and
c1.id_type_chart = 1942 and
c1.only_accrual = 1 and
c1.code not in ('99', '98')
更改主要逻辑,即去掉“code”列右边的'0',使用replace 查询正常执行,返回预期结果,除了一些偏离的行模式,在字符串的中间包含'0',而不是恰到好处。因此,我想我会使用返回错误的当前逻辑。知道这一点,错误所指的LEFT是子查询的LEFT,但是,如前所述,由于它是一个孤立的子查询,不依赖于外部因素,我不明白这个错误的原因。
那么,调试方法如下:
- 不使用 LEFT 时,不会出现错误
- 报错提示传给LEFT的长度无效
- LEFT 函数有问题
- 长度作为第二个参数传递
将 c1.code
替换为某个值:
Select
LEFT('100', (charindex('00', '100')-1)) "Código Conta"
有效,给你 1
但是.. 如果在值中找不到您要查找的字符串怎么办?
Select
LEFT('199', (charindex('00', '199')-1)) "Código Conta"
“无效长度...”错误
那么我们要经过多长时间?仅提取长度计算:
Select
charindex('00', '199')-1)
--LEFT('199', (charindex('00', '199')-1)) "Código Conta"
它给出 -1,而 -1 不是要从某物左侧删除的有效字符数...
大海捞针找不到,你想怎么办?也许在没有子字符串的情况下获取整个字符串?或者调整 WHERE 子句以仅允许以 00 结尾的代码,以便查找始终有效?
你决定.. 如果找不到“00”,这将为你提供全部信息:
Select
LEFT(
c1.code,
COALESCE(
NULLIF(
charindex('00', c1.code)-1,
-1
),
LEN(c1.Code)
)
) "Código Conta"
如果搜索 returns -1
表示“未找到”,NULLIF
将 -1 转换为 null
,然后 COALESCE
转换null
到字符串的 LEN
,即 LEFT
returns 整个
如果找不到字符串,这将给出空字符串;唯一的区别是在合并中使用 0 - 它要求 LEFT 给出最左边的 0 个字符:
Select
LEFT(
c1.code,
COALESCE(
NULLIF(
charindex('00', c1.code)-1,
-1
),
0
)
) "Código Conta"
或者,如前所述,使用 WHERE c1.code LIKE '%00%'
确保您只查看确实包含 00 的代码
如果没有子字符串'00'
LEFT(c1.code, (charindex('00', c1.code)-1))
会报错,因为 return 0 和 -1 无效
这会起作用:
CASE WHEN charindex('00', c1.code) > 0
THEN LEFT(c1.code, (charindex('00', c1.code)-1))
ELSE c1.code
END
这也适用:
LEFT(c1.code+'00', (charindex('00', c1.code+'00')-1))
我相信第二个会更快,但它可能不是基于您的数据配置文件,所以如果性能真的很重要,请测试两个。
顺便说一下,如果您只是想从数字中删除尾随的 0,您是否考虑过:
REPLACE((RTRIM(REPLACE(c1.code, '0', ' ')),' ', '0')
将所有的 0 改成空格,TRIM,并将剩余的空格改回来..
给猫剥皮的方法会更多;
REVERSE(CAST(REVERSE(c1.code) as INT))
(不过一般认为reverse有点nasty/slow)等..
我的问题很简单。下面查询returns错误:
Mensagem 537, Level 16, state 2, Line 1
Invalid length parameter passed to the LEFT or SUBSTRING function..
代码:
Select
c.name "Nome Conta",
c.code "Código Conta",
sq1.[Nome Conta] Tipo
From
(chart_tag ct inner join chart c on ct.id_chart = c.id_chart) inner join
(Select
c1.name "Nome Conta",
LEFT(c1.code, (charindex('00', c1.code)-1)) "Código Conta"
from chart_tag ct1 inner join chart c1 on ct1.id_chart = c1.id_chart
where ct1.id_tag = 18159 and
c1.id_type_chart = 1942 and
c1.only_accrual = 1 and
c1.code not in ('99', '98')) sq1 on LEFT(c.code, 1) = sq1.[Código Conta]
Where
ct.id_tag = 18159 and
c.id_type_chart = 1942 and
c.only_accrual = 0
order by
c.code
第一个内连接returns以下table:
Name | Code |
---|---|
Caixa Geral | 1111001 |
Caixa Departamentos/Operador | 1111005 |
Valores Recebidos a Depositar | 1111025 |
Bancos Conta Movimento | 1112001 |
Bancos Conta Movimento - Vincul | 1112005 |
Bancos Conta Subvenções | 1112021 |
Bancos Conta Doações | 1112022 |
Bancos Conta Contribuições | 1112023 |
Aplicações Financeiras Imediata | 1113001 |
Aplicações Financeiras Vinc. | 1113005 |
单独执行From子查询没有返回错误。生成如下table:
Name | code |
---|---|
ATIVO | 1 |
ATIVO CIRCULANTE | 11 |
CAIXA E EQUIVALENTES | 111 |
CAIXA | 1111 |
BANCOS | 1112 |
APLICAÇÕES FINANCEIRAS | 1113 |
来自
Name | code |
---|---|
ATIVO | 1000000 |
ATIVO CIRCULANTE | 1100000 |
CAIXA E EQUIVALENTES | 1110000 |
CAIXA | 1111000 |
BANCOS | 1112000 |
APLICAÇÕES FINANCEIRAS | 1113000 |
子查询:
Select
c1.name "Nome Conta",
LEFT(c1.code, (charindex('00', c1.code)-1)) "Código Conta"
from
chart_tag ct1 inner join chart c1 on ct1.id_chart = c1.id_chart
where
ct1.id_tag = 18159 and
c1.id_type_chart = 1942 and
c1.only_accrual = 1 and
c1.code not in ('99', '98')
更改主要逻辑,即去掉“code”列右边的'0',使用replace 查询正常执行,返回预期结果,除了一些偏离的行模式,在字符串的中间包含'0',而不是恰到好处。因此,我想我会使用返回错误的当前逻辑。知道这一点,错误所指的LEFT是子查询的LEFT,但是,如前所述,由于它是一个孤立的子查询,不依赖于外部因素,我不明白这个错误的原因。
那么,调试方法如下:
- 不使用 LEFT 时,不会出现错误
- 报错提示传给LEFT的长度无效
- LEFT 函数有问题
- 长度作为第二个参数传递
将 c1.code
替换为某个值:
Select
LEFT('100', (charindex('00', '100')-1)) "Código Conta"
有效,给你 1
但是.. 如果在值中找不到您要查找的字符串怎么办?
Select
LEFT('199', (charindex('00', '199')-1)) "Código Conta"
“无效长度...”错误
那么我们要经过多长时间?仅提取长度计算:
Select
charindex('00', '199')-1)
--LEFT('199', (charindex('00', '199')-1)) "Código Conta"
它给出 -1,而 -1 不是要从某物左侧删除的有效字符数...
大海捞针找不到,你想怎么办?也许在没有子字符串的情况下获取整个字符串?或者调整 WHERE 子句以仅允许以 00 结尾的代码,以便查找始终有效?
你决定.. 如果找不到“00”,这将为你提供全部信息:
Select
LEFT(
c1.code,
COALESCE(
NULLIF(
charindex('00', c1.code)-1,
-1
),
LEN(c1.Code)
)
) "Código Conta"
如果搜索 returns -1
表示“未找到”,NULLIF
将 -1 转换为 null
,然后 COALESCE
转换null
到字符串的 LEN
,即 LEFT
returns 整个
如果找不到字符串,这将给出空字符串;唯一的区别是在合并中使用 0 - 它要求 LEFT 给出最左边的 0 个字符:
Select
LEFT(
c1.code,
COALESCE(
NULLIF(
charindex('00', c1.code)-1,
-1
),
0
)
) "Código Conta"
或者,如前所述,使用 WHERE c1.code LIKE '%00%'
确保您只查看确实包含 00 的代码
如果没有子字符串'00'
LEFT(c1.code, (charindex('00', c1.code)-1))
会报错,因为 return 0 和 -1 无效
这会起作用:
CASE WHEN charindex('00', c1.code) > 0
THEN LEFT(c1.code, (charindex('00', c1.code)-1))
ELSE c1.code
END
这也适用:
LEFT(c1.code+'00', (charindex('00', c1.code+'00')-1))
我相信第二个会更快,但它可能不是基于您的数据配置文件,所以如果性能真的很重要,请测试两个。
顺便说一下,如果您只是想从数字中删除尾随的 0,您是否考虑过:
REPLACE((RTRIM(REPLACE(c1.code, '0', ' ')),' ', '0')
将所有的 0 改成空格,TRIM,并将剩余的空格改回来..
给猫剥皮的方法会更多;
REVERSE(CAST(REVERSE(c1.code) as INT))
(不过一般认为reverse有点nasty/slow)等..