从其他表中选择项目中的项目时选择值

时间:2018-11-16 08:01:42

标签: sql sql-server

表元素

ElementsName  ElementsCode
aaa           25
bbb           84
ccc           2
ddd           69
eee           158

表ElementsToCalc

Elements  SerialNum
25,2      1
69        2
158,84,2  3

我有以上两个表,想通过ElementsToCalc从Elements中选择值,如下面的代码

select * 
from Elements
where ElementsCode in (select Elements 
                       from ElementsToCalc 
                       where SerialNum = 1)

一无所获...

我认为它会像下面那样工作。

select * 
from Elements
where ElementsCode in (25,2)

如何使此代码像我想要的那样工作?

6 个答案:

答案 0 :(得分:1)

要使查询生效,可以使用以下查询。但是更好的选择是像上面的评论中那样重新设计架构。

select * 
  from Elements a
  join ElementsToCalc b  
    on ','+b.Elements+',' like '%,'+cast(a.ElementsCode as varchar(100))+',%'
 where b.serialnum=1

答案 1 :(得分:1)

在MS SQL Server 2016和更高版本中,您可以使用STRING_SPLIT从varchar中获取值。

示例代码段

declare @ElementsToCalc table (SerialNum int identity(1,1) primary key, [Elements] varchar(30));
insert into @ElementsToCalc ([Elements]) values 
('25,2'),
('69'),
('158,84,2');

declare @Elements table (ElementsName varchar(10), ElementsCode int);
insert into @Elements (ElementsName, ElementsCode) values
('aaa',25),
('bbb',84),
('ccc',2),
('ddd',69),
('eee',158);

with CALC as
(
 select SerialNum, try_cast(value as int) as Element
 from @ElementsToCalc ec
 cross apply string_split([Elements],',') spl
 where SerialNum = 1
)
select * 
from @Elements e
where ElementsCode in (select distinct Element from CALC);

如果您的版本中没有STRING_SPLIT,则可以在CTE中使用XML技巧。

with CALC as
(
  select SerialNum, x.value('.','int') as Element
  from (
   select SerialNum, cast('<x>'+replace([Elements],',','</x><x>')+'</x>' as XML) as XElements
   from ElementsToCalc
   where SerialNum = 1
  ) q
  cross apply XElements.nodes('/x') as n(x)
)
select * 
from Elements e
where ElementsCode in (select distinct Element from CALC);

答案 2 :(得分:1)

尝试一下:

CREATE FUNCTION [dbo].[tfn_Split]
(
    @string VARCHAR(8000) ,
    @SerialNum INT
)
RETURNS TABLE 
As
Return (
    SELECT str1.value , @SerialNum as SerialNum
    FROM  STRING_SPLIT(@string, ',') str1 
)  

DECLARE @ElementsToCalc TABLE (Elements nvarchar(50), SerialNum INT)
INSERT INTO @ElementsToCalc(Elements, SerialNum) VALUES('25,2',1)
INSERT INTO @ElementsToCalc(Elements, SerialNum) VALUES('69',2)
INSERT INTO @ElementsToCalc(Elements, SerialNum) VALUES('158,84,2',3)  

DECLARE @Elements TABLE (ElementsName nvarchar(50), ElementsCode INT)
INSERT INTO @Elements(ElementsName, ElementsCode) VALUES('aaa',25)
INSERT INTO @Elements(ElementsName, ElementsCode) VALUES('bbb',84)
INSERT INTO @Elements(ElementsName, ElementsCode) VALUES('ccc',2)
INSERT INTO @Elements(ElementsName, ElementsCode) VALUES('ddd',69)
INSERT INTO @Elements(ElementsName, ElementsCode) VALUES('eee',158)  

SELECT *
FROM   @Elements
WHERE  elementscode IN
       ( SELECT tb1.value
         FROM   @ElementsToCalc AS elc
                CROSS apply ( SELECT spl.serialnum,
                                     spl.value
                              FROM   dbo.Tfn_split ( elc.elements, elc.serialnum )     spl ) tb1
         WHERE  elc.serialnum = 1 )

答案 3 :(得分:0)

对于您正在使用的查询,应按如下所示修改第二张表

Elements  SerialNum
25        1
2         1
69        2
158       3
84        3
2         3

答案 4 :(得分:0)

尝试如下查询。

select * 
from Elements E
where EXISTS (select Elements 
              from ElementsToCalc ETC
              where ETC.SerialNum = 1 
              AND E.ElementsCode IN STRING_SPLIT(ETC.Elements, ','))

OR

select * 
from Elements E
where EXISTS (select Elements 
              from ElementsToCalc ETC
              where ETC.SerialNum = 1 
              AND Charindex(',' + ETC.Elements + ',', ',' + E.ElementsCode + ',') > 0)

答案 5 :(得分:0)

使用EXISTSCHARINDEX()

尝试以下操作
CREATE TABLE T1
    ([ElementsName] varchar(3), [ElementsCode] int);

INSERT INTO T1
    ([ElementsName], [ElementsCode])
VALUES
    ('aaa', 25),
    ('bbb', 84),
    ('ccc', 2),
    ('ddd', 69),
    ('eee', 158);

CREATE TABLE T2
    ([Elements] varchar(8), [SerialNum] int);

INSERT INTO T2
    ([Elements], [SerialNum])
VALUES
    ('25,2', 1),
    ('69', 2),
    ('158,84,2', 3);
SELECT *
FROM T1
WHERE EXISTS (SELECT 1 
              FROM T2
              WHERE T2.SerialNum = 1
              AND CHARINDEX(',' + CAST(T1.ElementsCode AS VARCHAR(11)) + ',', 
                            ',' + T2.Elements + ','
                           ) > 0
             );

返回:

+--------------+--------------+
| ElementsName | ElementsCode |
+--------------+--------------+
| aaa          |           25 |
| ccc          |            2 |
+--------------+--------------+

Demo