由逗号分隔的字符串中缺少值搜索

时间:2016-04-06 08:35:29

标签: sql sql-server tsql

请在sql中帮助我。

您好,也许有人请分享他们的专业知识,我不太确定它是否可以在SQL中

表的大小:5GB

我正在尝试查看给定VALIDATION_ID

的子表中存在的无效PRODUCT_LINE

在下面的情景114中,主表中的PRODUCT_LINE被动不存在但存在于子表中。

DECLARE @CHILD TABLE
(
  PRODUCT_LINE VARCHAR (50),
  COMPONENT VARCHAR (50),
  MODEL VARCHAR (50),
  YEARS VARCHAR (50),
  VALIDATION_ID VARCHAR (50)
)

INSERT @CHILD

SELECT 'PASSIVE','RESISTOR','CARBON','2005','V114' UNION ALL
SELECT 'PASSIVE','RESISTOR','CARBON','2005','V098, E009, V034'  UNION ALL
SELECT 'PASSIVE','RESISTOR','CARBON','2005','V201'  UNION ALL
SELECT 'PASSIVE','RESISTOR','CARBON','2005','V201,V098,V114' UNION ALL
SELECT 'PASSIVE','RESISTOR','CARBON','2005',null  UNION ALL
SELECT 'PASSIVE','RESISTOR','CARBON','2005','null,V098,E009'  UNION ALL
SELECT 'PASSIVE','RESISTOR','CARBON','2005','null,V114'  UNION ALL

SELECT * FROM @CHILD

DECLARE @PARENT TABLE
(
  PRODUCT_LINE VARCHAR (50),
  VALIDATION_ID VARCHAR (50)
)

INSERT @PARENT

SELECT 'PASSIVE','V098' UNION ALL
SELECT 'PASSIVE','E009' UNION ALL
SELECT 'PASSIVE','V201' UNION ALL
SELECT 'PASSIVE','V034' 

预期输出

 PRODUCT_LINE        COMPONENT    MODEL    YEARS    VALIDATION_ID  INVALID_VALIDATION_ID
 PASSIVE              RESISTOR    CARBON    2005    V114           V114
 PASSIVE              RESISTOR    CARBON    2005    V201,V098,V114 V114
'PASSIVE','RESISTOR','CARBON','2005','null,V114',V114

谢谢....

2 个答案:

答案 0 :(得分:0)

您肯定需要一个CSV分割器。有很多,只是搜索它。我在这里使用Jeff的DelimitedSplit8K()

SELECT  c.*, INVALID_VALIDATION_ID = v.Item
FROM    @CHILD c
        CROSS APPLY dbo.DelimitedSplit8K(c.VALIDATION_ID, ',') v
WHERE   NOT EXISTS
(
        SELECT  *
        FROM    @PARENT p
        WHERE   p.PRODUCT_LINE  = c.PRODUCT_LINE
        and p.VALIDATION_ID = LTRIM(v.Item)
)

如果有多个无效ID,它将显示为多行。如果您希望多个无效ID显示为CSV,则需要其他查询来连接它。如果您需要,请告诉我

编辑:更新了查询以在CSV中显示无效ID

; WITH
CTE AS
(
    SELECT  c.*, INVALID_VALIDATION_ID = v.Item, 
        RN = DENSE_RANK() OVER (ORDER BY PRODUCT_LINE, COMPONENT, MODEL, YEARS, VALIDATION_ID)
    FROM    @CHILD c
            CROSS APPLY dbo.DelimitedSplit8K(c.VALIDATION_ID, ',') v
    WHERE   c.VALIDATION_ID IS NOT NULL -- edit [2]
    AND     NOT EXISTS
        (
            SELECT  *
            FROM    @PARENT p
            WHERE   p.PRODUCT_LINE  = c.PRODUCT_LINE
            and p.VALIDATION_ID = LTRIM(v.Item)
        )
)
SELECT  DISTINCT 
    PRODUCT_LINE, COMPONENT, MODEL, YEARS, VALIDATION_ID,
    INVALID_VALIDATION_ID   = STUFF(csv, 1, 1, '')
FROM    CTE c
    CROSS APPLY
    (
        SELECT  ',' + x.INVALID_VALIDATION_ID
        FROM    CTE x
        WHERE   x.RN    = c.RN
        ORDER BY INVALID_VALIDATION_ID
        FOR XML PATH('')
    ) i (csv)

答案 1 :(得分:0)

你需要尝试这个......

SELECT *
FROM 
(
    SELECT  c.*, INVALID_VALIDATION_ID = x.Value
    FROM    @CHILD c
    CROSS APPLY dbo.Split(c.VALIDATION_ID, ',') x
    WHERE   NOT EXISTS
    (
        SELECT  *
        FROM    @PARENT p
        WHERE   p.PRODUCT_LINE  = c.PRODUCT_LINE
       and p.VALIDATION_ID = x.Value
    )  
) AS Q
WHERE INVALID_VALIDATION_ID IS NOT NULL AND  INVALID_VALIDATION_ID != 'null'

这里的dbo.split功能是..

CREATE FUNCTION [dbo].[Split]
(@List varchar(8000),@SplitOn varchar(5))

RETURNS @RtnValue table
(Id int identity(1,1),Value nvarchar(100))

AS
BEGIN
    Set @List = Replace(@List,'''','')
    While (Charindex(@SplitOn,@List)>0)

    Begin
            Insert Into @RtnValue (value)
            Select
            Value = ltrim(rtrim(Substring(@List,1,Charindex(@SplitOn,@List)-1)))

            Set @List = Substring(@List,Charindex(@SplitOn,@List)+len(@SplitOn),len(@List))
    End

    Insert Into @RtnValue (Value)
    Select Value = ltrim(rtrim(@List))

    Return
END

试试这个......