如何在 SQL Server 2008 中进行布尔字符串比较
How do I do a boolean string comparison in SQL Server 2008
简单来说,我想将一些列的内容加在一起,但前提是关联的列包含特定值。要在 MS Access 中执行此操作,我使用以下内容:
STRUint:(Abs(1*([Code01]='0192'))*[Code01int])+(Abs(1*([Code02]='0192'))*[Code02int])...
分解这个,如果 Code01='0192' 我得到结果 TRUE,我乘以 1 得到 -1 并使用 Abs 转换为 1。然后乘以 Code01int,所以我有一个仅当 Code01 为“0192”时整数才等于 Code01int,否则我将为零。该计算的结果将添加到序列中的下一个计算中,依此类推。
序列重复 15 次,将 Code01int 到 Code15int 中的整数相加,其中 Code01 到 Code15 的内容为'0192'
我个人认为在 SQL 中如何做到这一点的唯一方法是
UPDATE Table1
SET STRUint = 0
UPDATE Table1
SET STRUint = CASE
WHEN Code01='0192' THEN STRUint + Code01int
END
UPDATE Table1
SET STRUint = CASE
WHEN Code02='0192' THEN STRUint + Code02int
END
etc
这是通过多次更新实现我的目标的唯一方法吗?我对 15 组列执行此操作,并对不同的字符串内容重复 5 次,因此更新了 80 次(包括初始设置为零)。
我希望有一种方法可以在没有这么多更新的情况下做到这一点,假设最好不要做那么多。
你在 table 有身份证吗?
如果是,你可以这样做:
UPDATE A
SET STRUint = B.TOTAL
FROM TABLE1 A
INNER JOIN
(
SELECT ID,SUM(VALUE) AS TOTAL
FROM
(
SELECT ID,Code01int AS VALUE
FROM TABLE
WHERE Code01= '0192'
UNION ALL
SELECT ID,Code02int
FROM TABLE
WHERE Code02= '0192'
UNION ALL
SELECT ID,Code03int
FROM TABLE
WHERE Code03= '0192'
....
....
)A
GROUP BY ID
)B
ON A.ID = B.ID
有什么问题:
UPDATE Table1 SET STRUint = 0;
UPDATE
Table1
SET
STRUint +=
CASE WHEN Code01='0192' THEN Code01int ELSE 0 END
+ CASE WHEN Code02='0192' THEN Code02int ELSE 0 END
+ CASE WHEN Code03='0192' THEN Code03int ELSE 0 END
etc.
最好是更改 table 的设计。每当您觉得需要 name-number 列(例如 Code01
、Code02
)时,您应该使用相关的边 table.
我的代码将使用 APPLY
和 VALUES()
动态创建所需的结构(有点 unpivoting)然后 GROUP BY
和 SUM()
得到你想要的(我认为)。
DECLARE @MockTable TABLE(ID INT IDENTITY
,Comment VARCHAR(100)
,Code01 VARCHAR(100),Code01int INT
,Code02 VARCHAR(100),Code02int INT
,Code03 VARCHAR(100),Code03int INT);
INSERT INTO @MockTable VALUES('One is a' ,'a',1,'b',1,'c',1)
,('All are a','a',1,'a',1,'a',1)
,('Two are a','b',1,'a',1,'a',1);
--我用 'a' 代替你的号码,但你会得到 ghist
DECLARE @SearchCode VARCHAR(100)='a';
--查询
SELECT t.ID
,t.Comment
,SUM(A.Val) AS SumOfValuesForTheCode
FROM @MockTable t
CROSS APPLY (VALUES(1,Code01,Code01int)
,(2,Code02,Code02int)
,(3,Code03,Code03int))A(Indx,Code,Val)
WHERE A.Code=@SearchCode
GROUP BY t.ID,t.Comment
结果
1 One is a 1
2 All are a 3
3 Two are a 2
更新:完全通用的方法:
这不会很快,但它在某种程度上是美丽的:-)
SELECT t.ID
,t.Comment
,RowAsXml.query('for $code in /row/*[string-length(local-name())=6
and substring(local-name(),1,4)="Code"
and text()=sql:variable("@SearchCode")]
return /row/*[local-name()=concat(local-name($code),"int")]')
.value('sum(*/text())','int')
FROM @MockTable t
CROSS APPLY(SELECT t.* FOR XML PATH('row'),TYPE) A(RowAsXml)
简而言之:
APPLY
将创建代表整行的 XML。针对这个 XML 我们可以使用 XQuery 的 FLWOR。给定的 xquery 将 运行 通过节点并找到名称长度为 6 且以 "Code" 开头且 text()
(= 内容)等于您的值的节点正在寻找。
知道拟合代码节点,我们可以通过将列名与单词 "int".
连接来 return 拟合值节点
有了这个我们可以建立一个总和,瞧!
中间的 XML 看起来像这样(每行一个)
<row>
<Comment>One is a</Comment>
<Code01>a</Code01>
<Code01int>1</Code01int>
<Code02>b</Code02>
<Code02int>1</Code02int>
<Code03>c</Code03>
<Code03int>1</Code03int>
</row>
更新:如何更新 table 的列
您可以像这里一样使用联合查询
DECLARE @MockTable TABLE(ID INT IDENTITY
,Comment VARCHAR(100)
,Code01 VARCHAR(100),Code01int INT
,Code02 VARCHAR(100),Code02int INT
,Code03 VARCHAR(100),Code03int INT
,STRUint INT);
INSERT INTO @MockTable(Comment,Code01,Code01int,Code02,Code02int,Code03,Code03int)
VALUES('One is a' ,'a',1,'b',1,'c',1)
,('All are a','a',1,'a',1,'a',1)
,('Two are a','b',1,'a',1,'a',1);
DECLARE @SearchCode VARCHAR(100)='a';
UPDATE t1 SET STRUint=t2.SumOfValuesForTheCode
FROM
@MockTable t1
INNER JOIN
(
SELECT t.ID
,t.Comment
,SUM(A.Val) AS SumOfValuesForTheCode
FROM @MockTable t
CROSS APPLY (VALUES(1,Code01,Code01int)
,(2,Code02,Code02int)
,(3,Code03,Code03int))A(Indx,Code,Val)
WHERE A.Code=@SearchCode
GROUP BY t.ID,t.Comment
) t2 ON t1.ID=t2.ID;
--检查结果
SELECT * FROM @MockTable
另一种方法使用可更新的 CTE
WITH FindValue AS
(
SELECT t.ID
,SUM(A.Val) AS SumOfValuesForTheCode
FROM @MockTable t
CROSS APPLY (VALUES(1,Code01,Code01int)
,(2,Code02,Code02int)
,(3,Code03,Code03int))A(Indx,Code,Val)
WHERE A.Code=@SearchCode
GROUP BY t.ID,t.Comment
)
,TargetTable AS
(
SELECT t1.STRUint
,t2.SumOfValuesForTheCode
FROM @MockTable t1
INNER JOIN FindValue t2 ON t1.ID=t2.ID
)
UPDATE TargetTable SET STRUint=SumOfValuesForTheCode;
简单来说,我想将一些列的内容加在一起,但前提是关联的列包含特定值。要在 MS Access 中执行此操作,我使用以下内容:
STRUint:(Abs(1*([Code01]='0192'))*[Code01int])+(Abs(1*([Code02]='0192'))*[Code02int])...
分解这个,如果 Code01='0192' 我得到结果 TRUE,我乘以 1 得到 -1 并使用 Abs 转换为 1。然后乘以 Code01int,所以我有一个仅当 Code01 为“0192”时整数才等于 Code01int,否则我将为零。该计算的结果将添加到序列中的下一个计算中,依此类推。
序列重复 15 次,将 Code01int 到 Code15int 中的整数相加,其中 Code01 到 Code15 的内容为'0192'
我个人认为在 SQL 中如何做到这一点的唯一方法是
UPDATE Table1
SET STRUint = 0
UPDATE Table1
SET STRUint = CASE
WHEN Code01='0192' THEN STRUint + Code01int
END
UPDATE Table1
SET STRUint = CASE
WHEN Code02='0192' THEN STRUint + Code02int
END
etc
这是通过多次更新实现我的目标的唯一方法吗?我对 15 组列执行此操作,并对不同的字符串内容重复 5 次,因此更新了 80 次(包括初始设置为零)。
我希望有一种方法可以在没有这么多更新的情况下做到这一点,假设最好不要做那么多。
你在 table 有身份证吗? 如果是,你可以这样做:
UPDATE A
SET STRUint = B.TOTAL
FROM TABLE1 A
INNER JOIN
(
SELECT ID,SUM(VALUE) AS TOTAL
FROM
(
SELECT ID,Code01int AS VALUE
FROM TABLE
WHERE Code01= '0192'
UNION ALL
SELECT ID,Code02int
FROM TABLE
WHERE Code02= '0192'
UNION ALL
SELECT ID,Code03int
FROM TABLE
WHERE Code03= '0192'
....
....
)A
GROUP BY ID
)B
ON A.ID = B.ID
有什么问题:
UPDATE Table1 SET STRUint = 0;
UPDATE
Table1
SET
STRUint +=
CASE WHEN Code01='0192' THEN Code01int ELSE 0 END
+ CASE WHEN Code02='0192' THEN Code02int ELSE 0 END
+ CASE WHEN Code03='0192' THEN Code03int ELSE 0 END
etc.
最好是更改 table 的设计。每当您觉得需要 name-number 列(例如 Code01
、Code02
)时,您应该使用相关的边 table.
我的代码将使用 APPLY
和 VALUES()
动态创建所需的结构(有点 unpivoting)然后 GROUP BY
和 SUM()
得到你想要的(我认为)。
DECLARE @MockTable TABLE(ID INT IDENTITY
,Comment VARCHAR(100)
,Code01 VARCHAR(100),Code01int INT
,Code02 VARCHAR(100),Code02int INT
,Code03 VARCHAR(100),Code03int INT);
INSERT INTO @MockTable VALUES('One is a' ,'a',1,'b',1,'c',1)
,('All are a','a',1,'a',1,'a',1)
,('Two are a','b',1,'a',1,'a',1);
--我用 'a' 代替你的号码,但你会得到 ghist
DECLARE @SearchCode VARCHAR(100)='a';
--查询
SELECT t.ID
,t.Comment
,SUM(A.Val) AS SumOfValuesForTheCode
FROM @MockTable t
CROSS APPLY (VALUES(1,Code01,Code01int)
,(2,Code02,Code02int)
,(3,Code03,Code03int))A(Indx,Code,Val)
WHERE A.Code=@SearchCode
GROUP BY t.ID,t.Comment
结果
1 One is a 1
2 All are a 3
3 Two are a 2
更新:完全通用的方法:
这不会很快,但它在某种程度上是美丽的:-)
SELECT t.ID
,t.Comment
,RowAsXml.query('for $code in /row/*[string-length(local-name())=6
and substring(local-name(),1,4)="Code"
and text()=sql:variable("@SearchCode")]
return /row/*[local-name()=concat(local-name($code),"int")]')
.value('sum(*/text())','int')
FROM @MockTable t
CROSS APPLY(SELECT t.* FOR XML PATH('row'),TYPE) A(RowAsXml)
简而言之:
APPLY
将创建代表整行的 XML。针对这个 XML 我们可以使用 XQuery 的 FLWOR。给定的 xquery 将 运行 通过节点并找到名称长度为 6 且以 "Code" 开头且 text()
(= 内容)等于您的值的节点正在寻找。
知道拟合代码节点,我们可以通过将列名与单词 "int".
连接来 return 拟合值节点有了这个我们可以建立一个总和,瞧!
中间的 XML 看起来像这样(每行一个)
<row>
<Comment>One is a</Comment>
<Code01>a</Code01>
<Code01int>1</Code01int>
<Code02>b</Code02>
<Code02int>1</Code02int>
<Code03>c</Code03>
<Code03int>1</Code03int>
</row>
更新:如何更新 table 的列
您可以像这里一样使用联合查询
DECLARE @MockTable TABLE(ID INT IDENTITY
,Comment VARCHAR(100)
,Code01 VARCHAR(100),Code01int INT
,Code02 VARCHAR(100),Code02int INT
,Code03 VARCHAR(100),Code03int INT
,STRUint INT);
INSERT INTO @MockTable(Comment,Code01,Code01int,Code02,Code02int,Code03,Code03int)
VALUES('One is a' ,'a',1,'b',1,'c',1)
,('All are a','a',1,'a',1,'a',1)
,('Two are a','b',1,'a',1,'a',1);
DECLARE @SearchCode VARCHAR(100)='a';
UPDATE t1 SET STRUint=t2.SumOfValuesForTheCode
FROM
@MockTable t1
INNER JOIN
(
SELECT t.ID
,t.Comment
,SUM(A.Val) AS SumOfValuesForTheCode
FROM @MockTable t
CROSS APPLY (VALUES(1,Code01,Code01int)
,(2,Code02,Code02int)
,(3,Code03,Code03int))A(Indx,Code,Val)
WHERE A.Code=@SearchCode
GROUP BY t.ID,t.Comment
) t2 ON t1.ID=t2.ID;
--检查结果
SELECT * FROM @MockTable
另一种方法使用可更新的 CTE
WITH FindValue AS
(
SELECT t.ID
,SUM(A.Val) AS SumOfValuesForTheCode
FROM @MockTable t
CROSS APPLY (VALUES(1,Code01,Code01int)
,(2,Code02,Code02int)
,(3,Code03,Code03int))A(Indx,Code,Val)
WHERE A.Code=@SearchCode
GROUP BY t.ID,t.Comment
)
,TargetTable AS
(
SELECT t1.STRUint
,t2.SumOfValuesForTheCode
FROM @MockTable t1
INNER JOIN FindValue t2 ON t1.ID=t2.ID
)
UPDATE TargetTable SET STRUint=SumOfValuesForTheCode;