我有两个表,我们称它们为Users
和Fruit
。
用户
ID Name Fruit
-------------------
1 Bob 1,3
2 Jack 3
水果
ID Name
-------------
1 Apple
2 Orange
3 Grape
一个如何将这两个表结合起来以用用户选择的水果名称填充数据表?
我需要编写一个带有循环的存储过程吗?
我对SQL Server还是很陌生,很高兴获得任何帮助或将其指向正确的方向。
答案 0 :(得分:1)
首先,您需要重新设计表格。需要连接表,该表将保存哪个用户连接到哪个水果。这是N:N
的抢夺战。
因此,您应该创建这样的表:
FruitUser
UserId FruitId
1 1
1 3
2 3
UserId
是FK到Users
的表,FruitId
是FK到Fruits
的表,这两个列均构成组合主键。这是一种标准方法。
然后您可以使用简单的联接来获得结果:
select * from users u
join FruitUser fu on u.id = fu.userid
join Fruit f on f.id = fu.fruitId
答案 1 :(得分:1)
答案 2 :(得分:1)
样本数据
DECLARE @Users AS TABLE(ID INt, Name VARCHAR(100),fruit VARCHAR(100))
INSERT INTO @Users
SELECT 1,'Bob' ,'1,3' UNION ALL
SELECT 2,'Jack','3'
DECLARE @Fruit AS TABLE(ID INt, Name VARCHAR(100))
INSERT INTO @Fruit
SELECT 1,'Apple' UNION ALL
SELECT 2,'Orange'UNION ALL
SELECT 3,'Grape'
Sql脚本
;WITH CTE
AS
(
SELECT UserId,
UserName ,
CAST(Split.a.value('.', 'nvarchar(1000)') AS INT) AS FruitId
FROM
( SELECT u.ID AS UserId,
u.Name AS UserName ,
CAST( '<S>'+ REPLACE(fruit,',','</S><S>')+'</S>' AS XML) AS FruitId
FROM @Fruit f
INNER JOIN @Users u
ON u.ID=f.ID
)AS A
CROSS APPLY FruitId.nodes('S') AS Split(a)
)
SELECT Userid,
UserName,
FruitId,
ft.name AS FruitName
FROM CTE c
LEFT JOIN (SELECT * FROM @Fruit) AS Ft
ON ft.ID=c.FruitId
结果
Userid UserName FruitId FruitName
------------------------------------------
1 Bob 1 Apple
1 Bob 3 Grape
2 Jack 3 Grape
答案 3 :(得分:0)
通过此查询,您无需更改任何内容即可获得所需的结果
SELECT u.Id, u.Name, f.name
FROM Users u
inner join Fruit f on f.ID IN (SELECT cast(value as int)FROM STRING_SPLIT(u.fruit, ','));
由于拥有sql server 2014,因此具有各种选项,如CLR,XML和数字函数。最好的一种是CLR,但它很复杂。因此,您可以使用此XML代码。
select * from
(SELECT ID, [name],LTRIM(RTRIM(m.n.value('.[1]','varchar(8000)'))) AS fruitid
FROM
(SELECT ID,[name],CAST('<XMLRoot><RowData>' + REPLACE(fruit,',','</RowData><RowData>') + '</RowData></XMLRoot>' AS XML) AS x FROM {User table})t
CROSS APPLY x.nodes('/XMLRoot/RowData')m(n)) u
inner join {fruit table} f on f.id = u.fruitid
答案 4 :(得分:0)
使用示例数据创建的物理表
CREATE TABLE TempUsers
( ID INT,
Name VARCHAR(100),
Fruit VARCHAR(100)
)
INSERT INTO TempUsers
SELECT 1,'Bob' ,'1,3' UNION ALL
SELECT 2,'Jack','3'
CREATE TABLE TempFruit
( ID INT,
Name VARCHAR(100))
INSERT INTO TempFruit
SELECT 1,'Apple' UNION ALL
SELECT 2,'Orange'UNION ALL
SELECT 3,'Grape'
创建一个表值函数,以逗号分隔的形式检索水果名称
CREATE FUNCTION [dbo].[udf_GetFruitNames]
(
@vc_String nvarchar(max)
)
RETURNS @OutTable TABLE
(
Reqdata nvarchar(max)
)
AS
BEGIN
DECLARE @Temp AS TABLE
(
DATA nvarchar(max)
)
INSERT INTO @Temp
SELECT @vc_String;
DECLARE @Temp1 AS TABLE
(
DATA nvarchar(max)
)
INSERT INTO @Temp1
SELECT
STUFF((SELECT DISTINCT ','+ Name FROM
(
SELECT ID,
Name
FROm TempFruit
WHERE ID IN ( SELECT
CAST(Split.a.value('.', 'nvarchar(1000)') AS INT) AS FruitId
FROM
( SELECT
CAST( '<S>'+ REPLACE(DATA,',','</S><S>')+'</S>' AS XML) AS FruitId
FROM @Temp f
)AS A
CROSS APPLY FruitId.nodes('S') AS Split(a))
) As dt FOR XML PATH ('')),1,1,'') As FruitName
INSERT INTO @OutTable
SELECT * FROM @Temp1
RETURN
END
SQL查询
SELECT ID
,Name
,uf.Reqdata AS FruitNames
FROM TempUsers u
CROSS APPLY [dbo].[udf_GetFruitNames](u.Fruit) AS uf
Or
SELECT ID
,Name
,(SELECT Reqdata FROM [dbo].[udf_GetFruitNames](u.Fruit) ) AS FruitNames
FROM TempUsers u
结果
ID Name FruitNames
---------------------
1 Bob Apple,Grape
2 Jack Grape