首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何根据另一列中逗号分隔的值按名称引用列?

如何根据另一列中逗号分隔的值按名称引用列?
EN

Stack Overflow用户
提问于 2021-07-27 17:22:06
回答 3查看 56关注 0票数 0

我有张桌子看起来像这样:

代码语言:javascript
运行
复制
PartNumber    Part    ValuesList    x1    x2    x3    x4
123456        Fender  x1            11    10    9     12
123456        Fender  x1,x2         11    10    9     12
123456        Fender  x2,x4         11    10    9     12
123456        Fender  x1,x2,x3,x4   11    10    11    12
123456        Fender  x2,x3,x4      11    10    9     12

对于每一行,如何根据列x1、x2、x3、x4中给出的列名找到最低值?

例如,第1行很简单。ValuesList值是x1,所以我只需要查看列x1,最低值是11。

第二排..。ValuesList值为x1,x2。我需要x1列和x2列(11和10)之间的较低的编号。最低值为10。

第三排..。ValuesList值为x2,x4。我需要列x2和x4 (10和12)之间的较低的编号。最低值为10。

第四排..。ValuesList值为x1、x2、x3、x4。我需要列x1、x2、x3和x4 (11、10、11、12)之间的较低编号。最低值是10。

第5排..。ValuesList值为x2、x3、x4。我需要x2、x3和x4列(10、9、12)之间的较低的编号。最低值为9。

实际的表有数十万行。

在伪码中,我想要的是

代码语言:javascript
运行
复制
SELECT PartNumber, Part, MIN(ColumnValue) WHERE ColumnName IN (SELECT ColumnNames FROM ValuesList)

如果最低的数字出现在多个列中,那么从哪个列取最低的数字并不重要。

谢谢!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-07-27 17:32:49

我将假设您在这里使用的是最新版本的Server,因此可以访问STRING_SPLIT。如果没有,那么您将需要使用用户定义的字符串拆分器;如果您进行搜索(虽然我建议使用基于集合的字符串拆分器),那么就有大量的字符串拆分器。然后,沿着STRING_SPLIT,您可以解除数据的枢轴,为此,我使用一个表VALUES构造,在WHERE中隐式地使用JOIN,最后聚合:

代码语言:javascript
运行
复制
CREATE TABLE dbo.YourTable (PartNumber int,
                            Part varchar(10),
                            ValuesList varchar(8000),
                            x1 int,
                            x2 int,
                            x3 int,
                            x4 int);
GO
INSERT INTO dbo.YourTable
VALUES(123456,'Fender','x1         ',11,10,9 ,12),
      (123456,'Fender','x1,x2      ',11,10,9 ,12),
      (123456,'Fender','x2,x4      ',11,10,9 ,12),
      (123456,'Fender','x1,x2,x3,x4',11,10,11,12),
      (123456,'Fender','x2,x3,x4   ',11,10,9 ,12);
GO

SELECT YT.PartNumber,
       YT.Part,
       YT.ValuesList,
       MIN(V.XVal) AS MinX
FROM dbo.YourTable YT
     CROSS APPLY STRING_SPLIT(YT.ValuesList,',') SS
     CROSS APPLY (VALUES(N'x1',x1),
                        (N'x2',x2),
                        (N'x3',x3),
                        (N'x4',x4))V(XCol,XVal)
WHERE SS.[value] = V.XCol
GROUP BY YT.PartNumber,
         YT.Part,
         YT.ValuesList;
GO

DROP TABLE dbo.YourTable;

当然,我真的建议你在这里规范化你的设计。不要存储分隔的数据,也不要重复列值。如果您将您的设计规范化,您可能只需要几个JOIN和一个聚合。

票数 4
EN

Stack Overflow用户

发布于 2021-07-27 18:01:23

只是另一种选择

示例

代码语言:javascript
运行
复制
Select A.PartNumber
      ,A.Part
      ,A.ValuesList
      ,B.MinValue 
 From  YourTable A
 Cross Apply ( Select MinValue=min(Value)
                From  (values (case when charindex('x1',ValuesList)>0 then x1 end)
                             ,(case when charindex('x2',ValuesList)>0 then x2 end)
                             ,(case when charindex('x3',ValuesList)>0 then x3 end)
                             ,(case when charindex('x4',ValuesList)>0 then x4 end)
                      ) B1(Value)
             )B

结果

代码语言:javascript
运行
复制
PartNumber  Part    ValuesList  MinValue
123456      Fender  x1          11
123456      Fender  x1,x2       10
123456      Fender  x1,x2,x3,x4 10
123456      Fender  x2,x3,x4    9
123456      Fender  x2,x4       10
票数 1
EN

Stack Overflow用户

发布于 2021-07-27 18:17:43

我强烈建议在没有外部group by的情况下这样做。

代码语言:javascript
运行
复制
SELECT t.*, s.min_val
FROM t OUTER APPLY
     (SELECT MIN(val) as min_val
      FROM STRING_SPLIT(YT.ValuesList,',') s JOIN
           (VALUES('x1', x1), ('x2', x2), ('x3', x3),('x4', x4)
           )v(col, val)
           ON s.value = v.name
     ) s;

对行内的值使用APPLY通常比对整个数据集进行聚合具有更好的性能特征。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68549299

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档