SQL头脑风暴

时间:2015-06-06 06:58:01

标签: sql-server tsql

通过构建文本字段来寻求关于联接的帮助。

表1称为驱动程序表,它告诉哪个basepart属性必须与哪些likepart属性进行比较。

所有行动和比较将在表2中进行。

如果basepart中出现的任何值和缺少相同部分的值应该输出带有消息列,例如: - (使15不能与basepart MCN442941一起使用)。同样适用于Basepart。

如果两列单行存在差异,则两者都应该在输出中。

下面给出了预期输出的样本表。

CREATE TABLE DRIVER 
(
  BasePart varchar(50),
  likepart varchar (50)
)

insert into DRIVER select 'MCNW10',   'MCNW10__'  
insert into DRIVER select 'MCNW20',   'MCNW20__'
insert into DRIVER select 'MCN442941','MCN4_2941'

CREATE TABLE PARTS
(
  part varchar(50), 
  Make varchar(50), 
  Model varchar(50),
  Year varchar(50),
  remarks varchar(50),
  remarks2 varchar(50),
  remarks3 varchar(50)
)

insert into Parts select 'MCNW10','40','353','2001','FLOORMAT','CLASS','FRONT'
insert into Parts select 'MCNW10','40','353','2001','FLOORMAT','CLASS','FRONT'
insert into Parts select 'MCNW20','90','555','2015','DOORMAT','CLASS','REAR'
insert into Parts select 'MCNW20','90','555','2015','DOORMAT','CLASS','REAR'
insert into Parts select 'MCNW10','555','111','1975','CATCH ME','CLASS','FRONT'
insert into Parts select 'MCNW10GR','40','353','2001','FLOORMAT','CLASS','FRONT'
insert into Parts select 'MCNW10TN','40','8888','2001','FLOORMAT','CLASS','FRONTREAR'
INSERT INTO Parts SELECT 'MCN442941','65','548','2007','SLE, CREW ','front','V335'
INSERT INTO Parts SELECT 'MCN442941','65','548','2007','SLE, CREW ','front','V335'
INSERT INTO Parts SELECT 'MCN442941','A65','B548','2025','SLE, CREW ','front','V335'
INSERT INTO Parts SELECT 'MCN452941','65','548','2007','SLE, CREW ','front','V335'
INSERT INTO Parts SELECT 'MCN452941','65','548','2007','SLE, CREW ',  ''   ,'V335'
INSERT INTO Parts SELECT 'MCN482941','15','222','2016','SLE, CREW ','front','V335'
INSERT INTO Parts SELECT 'MCN442941','A65','B548','2025','SLE, CREW ','front','V335'

和带有别名消息列的预期输出。消息列是必需的。

--expected  output
/*
 part      ,Make    ,Model ,Year  ,remarks         remarks2      remarks3    BasePart    likepart      (comment)
'MCNW10TN','40',   '8888','2001','FLOORMAT',      'CLASS',     'FRONTREAR', MCNW10,    MCNW10TN,    8888 model is not available with base part MCNW10
'MCNW10TN','40',   '8888','2001','FLOORMAT',      'CLASS',     'FRONTREAR', MCNW10,    MCNW10TN,    FRONTREAR Remarks3 is not available with base part MCNW10
'MCNW10'  ,'555'   ,'111','1975','CATCH ME'       ,'CLASS'     ,'FRONT' ,   MCNW10,    MCNW10GR,    Catch me is not available with like part MCNW10GR
'MCNW10'  ,'555'   ,'111','1975','CATCH ME'       ,'CLASS'     ,'FRONT' ,   MCNW10,    MCNW10TN,    Catch me is not available with like part MCNW10TN
'MCN452941','65',   '548','2007','SLE, CREW ',      '',         'V335'  ,  MCN442941,  MCN452941,  '' remarks2 is not available with base part MCN442941
'MCN482941','15',   '222','2016','SLE, CREW ',     'front',     'V335', MCN442941,     MCN452941,   Make 15 is not available with basepart  MCN442941
'MCN482941','15',   '222','2016','SLE, CREW ',     'front',     'V335', MCN442941,     MCN452941,   Model 222 is not available with basepart  MCN442941
'MCN482941','15',   '222','2016','SLE, CREW ',     'front',     'V335', MCN442941,     MCN452941,   Year 2016 is not available with basepart  MCN442941
'MCN442941','A65',  'B548','2025','SLE, CREW ',    'front',     'V335', MCN442941,     MCN452941,   MAKE A65 is not present with like part MCN452941
'MCN442941','A65',  'B548','2025','SLE, CREW ',    'front',     'V335', MCN442941,     MCN452941,   Model B548 is not present with like part MCN452941
'MCN442941','A65',  'B548','2025','SLE, CREW ',    'front',     'V335', MCN442941      MCN452941,   year 2025 is not present with like part MCN452941
'MCN442941','A65',  'B548','2025','SLE, CREW ',    'front',     'V335', MCN442941      MCN482941,   MAKE A65 is not present with like part MCN482941
'MCN442941','A65', 'B548','2025','SLE, CREW ',    'front',     'V335', MCN442941      MCN482941    Model B548 is not present with like part MCN482941
'MCN442941','A65',  'B548','2025','SLE, CREW ',    'front',     'V335', MCN442941      MCN482941,   year 2025 is not present with like part MCN482941

我已尝试过此代码,但未能形成评论栏

 SELECT   DISTINCT
     B.part AS BasePart ,
     L.part AS LikePart ,
     STUFF(IIF(B.make != L.make, ', make: ' + L.make, '') + IIF(B.model != L.model, ', model: ' + L.model, '')
           + IIF(B.[year] != L.[year], ', year: ' + L.[year], '') + IIF(B.remarks != L.remarks, ', remarks: ' + L.remarks, '')
           + IIF(B.remarks2 != L.remarks2, ', remarks2: ' + L.remarks2, '') + IIF(B.remarks3 != L.remarks3, ', remarks3: ' +
     L.remarks, ''), 1, 2, '') AS attrib_diff FROM    @Parts B
     INNER JOIN @Driver D ON D.BasePart = B.part
     INNER JOIN @Parts L ON L.part LIKE D.likepart WHERE   B.part != L.part;

1 个答案:

答案 0 :(得分:0)

SQL Server中没有IIF功能。您应该使用CASE表达式:

SELECT   DISTINCT
     B.part AS BasePart ,
     L.part AS LikePart ,
     STUFF(
        CASE WHEN B.make != L.make THEN ', make: ' + L.make ELSE '' END
        + CASE WHEN B.model != L.model THEN ', model: ' + L.model ELSE '' END
        + CASE WHEN B.[year] != L.[year] THEN ', year: ' + L.[year] ELSE '' END
        + CASE WHEN B.remarks != L.remarks THEN ', remarks: ' + L.remarks ELSE '' END
        + CASE WHEN B.remarks2 != L.remarks2 THEN ', remarks2: ' + L.remarks2 ELSE '' END
        + CASE WHEN B.remarks3 != L.remarks3 THEN ', remarks3: ' + L.remarks3 ELSE '' END
    , 1, 2, '') AS attrib_diff 
FROM    Parts B
INNER JOIN Driver D ON D.BasePart = B.part
INNER JOIN Parts L ON L.part LIKE D.likepart WHERE   B.part != L.part;

然而,你的表结构似乎很奇怪。为什么零件表中有重复项?

稍后编辑(6月23日):关于您的评论,我不确定我是否理解正确,但请尝试以下内容:

SELECT *
FROM (
    SELECT  DISTINCT
         B.part AS BasePart ,
         L.part AS LikePart ,
         X.Attribute,
         CASE x.Attribute
            WHEN 'make' THEN B.Make
            WHEN 'model' THEN B.Model
            WHEN 'year' THEN B.Year
            WHEN 'remarks' THEN B.remarks
            WHEN 'remarks2' THEN B.remarks2
            WHEN 'remarks3' THEN B.remarks3
        END AS BaseAttribute,
        CASE x.Attribute
            WHEN 'make' THEN L.Make
            WHEN 'model' THEN L.Model
            WHEN 'year' THEN L.Year
            WHEN 'remarks' THEN L.remarks
            WHEN 'remarks2' THEN L.remarks2
            WHEN 'remarks3' THEN L.remarks3
        END AS LikeAttribute
    FROM    Parts B
    INNER JOIN Driver D ON D.BasePart = B.part
    INNER JOIN Parts L ON L.part LIKE D.likepart 
    CROSS JOIN (
        SELECT 'make' AS Attribute
        UNION ALL SELECT 'model' AS Attribute
        UNION ALL SELECT 'year' AS Attribute
        UNION ALL SELECT 'remarks' AS Attribute
        UNION ALL SELECT 'remarks2' AS Attribute
        UNION ALL SELECT 'remarks3' AS Attribute
    ) X
    WHERE   B.part != L.part
) Q WHERE BaseAttribute<>LikeAttribute

稍后编辑(7月1日):考虑您的最新评论,您可以使用此查询:

SELECT *, 
    CASE 
        WHEN Y.BaseAttribute IS NULL AND Y.LikeAttribute IS NOT NULL
        THEN Attribute+' '+LikeAttribute+' is not available with basepart '+BasePart+' but it is present with like part'
        WHEN Y.BaseAttribute IS NOT NULL AND Y.LikeAttribute IS NULL
        THEN Attribute+' '+BaseAttribute+' is not available with like part '+likepart+' but it is present with base part'
    END AS Message
FROM dbo.DRIVER D
CROSS JOIN (
    SELECT 'make' AS Attribute
    UNION ALL SELECT 'model' AS Attribute
    UNION ALL SELECT 'year' AS Attribute
    UNION ALL SELECT 'remarks' AS Attribute
    UNION ALL SELECT 'remarks2' AS Attribute
    UNION ALL SELECT 'remarks3' AS Attribute
) X
OUTER APPLY (
    SELECT *
    FROM (
        SELECT CASE X.Attribute
                WHEN 'make' THEN B.Make
                WHEN 'model' THEN B.Model
                WHEN 'year' THEN B.Year
                WHEN 'remarks' THEN B.remarks
                WHEN 'remarks2' THEN B.remarks2
                WHEN 'remarks3' THEN B.remarks3
            END AS BaseAttribute
        FROM dbo.PARTS B
        WHERE B.part=D.BasePart
    ) Y1
    FULL OUTER JOIN (
        SELECT CASE X.Attribute
                WHEN 'make' THEN L.Make
                WHEN 'model' THEN L.Model
                WHEN 'year' THEN L.Year
                WHEN 'remarks' THEN L.remarks
                WHEN 'remarks2' THEN L.remarks2
                WHEN 'remarks3' THEN L.remarks3
            END AS LikeAttribute
        FROM dbo.PARTS L
        WHERE L.part LIKE D.likepart
    ) Y2 ON Y1.BaseAttribute=Y2.LikeAttribute
) Y 
WHERE Y.BaseAttribute IS NULL AND Y.LikeAttribute IS NOT NULL 
    OR Y.BaseAttribute IS NOT NULL AND Y.LikeAttribute IS NULL