Sql server SQL Server列拆分

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, ...

我刚开始使用SQL查询,所以我还没有真正的经验

我试着去查这个,但我不明白其中的大部分(也不知道它是否真的适合我的问题),所以我很想解释一下你会怎么解决它以及为什么

如果你问我的话,我使用的数据库有时处理数据效率很低

数据库结构如下:

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 |
+-------------+