Sql 查询以检索以下数据
Sql Query to retrieve following data
我有一个包含 3 列的 table。前两列是 ID(主键)和国家/地区。第三列包含一些用冒号字符分隔的名称。例如:
ID Country Names
--------------------------
1 USA Mike;Bill
2 USA Michael;Lara;Van
3 Italy Kobe;Nate;Tim;Manu
我需要编写一个 SQL 查询,为每个名称生成一个新行。例如,在这种情况下,输出将是
ID Country Name
--------------------------
1 USA Mike
1 USA Bill
2 USA Michael
2 USA Lara
2 USA Van
3 Italy Kobe
3 Italy Nate
3 Italy Tim
3 Italy Manu
我该怎么做?我在 t-sql 中找到了一个拆分函数,它可以拆分关于一个字符的字符串。但是如何将数据拆分成多行呢?
您可以创建一个新的 table 并使用循环 INSERT
:
SET NOCOUNT ON
DECLARE @intFlag INT
SET @intFlag = 1
WHILE (@intFlag <= (SELECT MAX(LEN(REPLACE(Names,';',';;')) - LEN(Names)) FROM YourOldTable))
BEGIN
INSERT INTO YourNewTable
SELECT ID,Country
, Name = dbo.FN_PARSE([Names],';',@intFlag)
FROM YourOldTable
WHERE dbo.FN_PARSE([Names],';',@intFlag) IS NOT NULL
SET @intFlag = @intFlag + 1
END
GO
SET NOCOUNT OFF
您的语法可能因 split/parse 函数而异。
任务是将名称拆分成各自的行,然后将这些行放入单个结果集中。
我们可以将此 QA 中的此函数用作拆分函数 (T-SQL: Opposite to string concatenation - how to split string into multiple records),因为它是一个 table 值函数,我们可以像处理任何其他形式的表格一样处理结果集数据(例如 table、视图、临时 table、table 变量等)
CREATE FUNCTION dbo.SplitStr( @sep char(1), @s nvarchar(512) )
RETURNS table
AS
RETURN (
WITH Pieces(pn, start, stop) AS (
SELECT 1, 1, CHARINDEX( @sep, @s )
UNION ALL
SELECT pn + 1, stop + 1, CHARINDEX( @sep, @s, stop + 1 )
FROM Pieces
WHERE stop > 0
)
SELECT
pn,
SUBSTRING( @s, start, CASE WHEN stop > 0 THEN stop-start ELSE 512 END ) AS s
FROM
Pieces
)
然后我们需要为 CountryNames
table 中的每一行调用此函数并合并结果。如果我们使用 CROSS APPLY
,这实际上是一个单行,所以需要的查询就是这样:
SELECT
CountryNames.ID,
CountryNames.Country,
Splat.s
FROM
CountryNames
CROSS APPLY
dbo.SplitStr(';', CountryNames.Names ) As Splat
哒哒!
请注意,如果这是一个高性能应用程序或使用大型 table,则在应用程序代码中执行此数据转换可能很有意义。至少尝试规范化您的数据,这样您就不需要 运行 每次要查找此信息时都使用此代码。
我有一个包含 3 列的 table。前两列是 ID(主键)和国家/地区。第三列包含一些用冒号字符分隔的名称。例如:
ID Country Names
--------------------------
1 USA Mike;Bill
2 USA Michael;Lara;Van
3 Italy Kobe;Nate;Tim;Manu
我需要编写一个 SQL 查询,为每个名称生成一个新行。例如,在这种情况下,输出将是
ID Country Name
--------------------------
1 USA Mike
1 USA Bill
2 USA Michael
2 USA Lara
2 USA Van
3 Italy Kobe
3 Italy Nate
3 Italy Tim
3 Italy Manu
我该怎么做?我在 t-sql 中找到了一个拆分函数,它可以拆分关于一个字符的字符串。但是如何将数据拆分成多行呢?
您可以创建一个新的 table 并使用循环 INSERT
:
SET NOCOUNT ON
DECLARE @intFlag INT
SET @intFlag = 1
WHILE (@intFlag <= (SELECT MAX(LEN(REPLACE(Names,';',';;')) - LEN(Names)) FROM YourOldTable))
BEGIN
INSERT INTO YourNewTable
SELECT ID,Country
, Name = dbo.FN_PARSE([Names],';',@intFlag)
FROM YourOldTable
WHERE dbo.FN_PARSE([Names],';',@intFlag) IS NOT NULL
SET @intFlag = @intFlag + 1
END
GO
SET NOCOUNT OFF
您的语法可能因 split/parse 函数而异。
任务是将名称拆分成各自的行,然后将这些行放入单个结果集中。
我们可以将此 QA 中的此函数用作拆分函数 (T-SQL: Opposite to string concatenation - how to split string into multiple records),因为它是一个 table 值函数,我们可以像处理任何其他形式的表格一样处理结果集数据(例如 table、视图、临时 table、table 变量等)
CREATE FUNCTION dbo.SplitStr( @sep char(1), @s nvarchar(512) )
RETURNS table
AS
RETURN (
WITH Pieces(pn, start, stop) AS (
SELECT 1, 1, CHARINDEX( @sep, @s )
UNION ALL
SELECT pn + 1, stop + 1, CHARINDEX( @sep, @s, stop + 1 )
FROM Pieces
WHERE stop > 0
)
SELECT
pn,
SUBSTRING( @s, start, CASE WHEN stop > 0 THEN stop-start ELSE 512 END ) AS s
FROM
Pieces
)
然后我们需要为 CountryNames
table 中的每一行调用此函数并合并结果。如果我们使用 CROSS APPLY
,这实际上是一个单行,所以需要的查询就是这样:
SELECT
CountryNames.ID,
CountryNames.Country,
Splat.s
FROM
CountryNames
CROSS APPLY
dbo.SplitStr(';', CountryNames.Names ) As Splat
哒哒!
请注意,如果这是一个高性能应用程序或使用大型 table,则在应用程序代码中执行此数据转换可能很有意义。至少尝试规范化您的数据,这样您就不需要 运行 每次要查找此信息时都使用此代码。