Sql server SQL Server列拆分
我刚开始使用SQL查询,所以我还没有真正的经验 我试着去查这个,但我不明白其中的大部分(也不知道它是否真的适合我的问题),所以我很想解释一下你会怎么解决它以及为什么 如果你问我的话,我使用的数据库有时处理数据效率很低 数据库结构如下:Sql server SQL Server列拆分,sql-server,stored-procedures,multiple-columns,Sql Server,Stored Procedures,Multiple Columns,我刚开始使用SQL查询,所以我还没有真正的经验 我试着去查这个,但我不明白其中的大部分(也不知道它是否真的适合我的问题),所以我很想解释一下你会怎么解决它以及为什么 如果你问我的话,我使用的数据库有时处理数据效率很低 数据库结构如下: USE [TestDatabase] CREATE TABLE [dbo].[fruits]( ...(other columns) [diffruits1] int, NOT NULL [diffruits2] [varchar](100) NULL, ...
USE [TestDatabase]
CREATE TABLE [dbo].[fruits](
...(other columns)
[diffruits1] int, NOT NULL
[diffruits2] [varchar](100) NULL,
...
)
这一列(Diffuits2)会这样说:
"apples=1000, bananas=2, oranges=1, blueberries=102"
现在我的目标是使用苹果的1000个值(或蓝莓的102个值)
用于IF语句或其他计算。我认为需要将varchar转换为int
像这样:
IF diffruits1=103
BEGIN
IF apples >= 1000
BEGIN
example.statement
END
IF blueberries =10
BEGIN
example.statement2
END
END
差不多吧。我知道我可能会将列拆分为“=”和“,”,但老实说,我只是不知道如何拆分。我想将其用于一个过程。如果无法更改表结构,可以使用字符串拆分函数创建一个可以使用的视图 创建并填充样本表(请在以后的问题中保存此步骤): 如果您使用的是sql server 2016,则可以使用内置的
STRING\u SPLIT
功能。对于较低版本,您需要先创建函数。对于这个答案,我选择使用一个基于Jeff Moden的spliter的函数,取自Aaron Bertrand的文章: 使用split string函数后,可以创建如下视图:
CREATE VIEW vw_Splitted AS
SELECT diffruits1,
LTRIM(RTRIM(LEFT(Item, CHARINDEX('=', Item)-1))) As Name,
CAST(RIGHT(Item, LEN(Item) - CHARINDEX('=', Item)) As int) As Value
FROM fruits
CROSS APPLY dbo.SplitStrings(diffruits2, ',')
测试视图:
SELECT *
FROM vw_Splitted
结果:
diffruits1 Name Value
1 apples 1000
1 bananas 2
1 oranges 1
1 blueberries 102
您可以在上看到一个实时演示:这与Zohar Peled的答案类似,但我想进一步说明如何在过程中使用拆分函数来运行所需的条件 rextester演示: 返回:
+----+---------+-------------+----------+
| Id | Ordinal | Fruit | Quantity |
+----+---------+-------------+----------+
| 1 | 1 | apples | 1 |
| 1 | 2 | bananas | 2 |
| 1 | 3 | oranges | 3 |
| 1 | 4 | blueberries | 10 |
| 2 | 1 | apples | 1000 |
| 2 | 2 | bananas | 2 |
| 2 | 3 | oranges | 1 |
| 2 | 4 | blueberries | 102 |
+----+---------+-------------+----------+
拆分字符串引用:
您可以在您的程序中使用它,如下所示:
go
create procedure dbo.fruitful (@id int) as
begin;
set nocount, xact_abort on;
select
t.Id
, Ordinal = s.ItemNumber
, Fruit = ltrim(left(s.Item,charindex('=',s.Item)-1))
, Quantity = stuff(s.Item,1,charindex('=',s.Item),'')
into #temp_fruit
from t
cross apply dbo.delimitedsplit8K(diffruits2,', ') s
where t.id = @id;
if exists (
select 1
from #temp_fruit
where Fruit='apples'
and Quantity>=1000
)
begin;
/* steal an apple, or other code */
select 1 as AppleStolen;
end;
if exists (
select 1
from #temp_fruit
where Fruit='blueberries'
and Quantity=10
)
begin;
/* give them 2 more blueberries, just to be nice. or other code. */
select 2 as BlueberriesAdded;
end;
end;
go
添加的id为1的字符串的示例过程:
exec dbo.fruitful 1;
返回:
+------------------+
| BlueberriesAdded |
+------------------+
| 2 |
+------------------+
+-------------+
| AppleStolen |
+-------------+
| 1 |
+-------------+
对于原始字符串:
exec dbo.fruitful 2;
返回:
+------------------+
| BlueberriesAdded |
+------------------+
| 2 |
+------------------+
+-------------+
| AppleStolen |
+-------------+
| 1 |
+-------------+
您的问题不清楚。请参阅参考链接,了解如何提出一个完美的问题:您是否可以先规范化结构,或者结构是否已给定且无法更改?将此类数据存储在数据库表中是一个错误。拆分不足以解析此类数据。您应该在加载到数据库之前解析数据,并将其存储在设计良好的表中。您只需要一个单独的表,其中包含
水果名
,计数
,以及ParentTableId列,以便首先规范化数据,然后按照通常的方式进行查询。此外,过滤数据是使用WHERE
,而不是IF
。为了使用IF
,您必须逐行浏览所有数据。服务器执行WHERE
语句的速度比循环快几百倍,特别是水果名
列上有索引的情况下,非常感谢@乔伊很乐意帮忙!谢谢!这就是我需要的
+-------------+
| AppleStolen |
+-------------+
| 1 |
+-------------+