标记在7天内相互匹配 - 而不是在7天内

时间:2015-01-15 12:25:41

标签: sql-server tsql

给出一张表:

----------------------------------------
REF   |  Date      |  Product |  Mark  |
----------------------------------------
1     | 01/01/2014 | A        |   X
1     | 07/01/2014 | B        |   X
1     | 14/01/2014 | C        |   X
1     | 21/01/2014 | A        |   X
1     | 31/01/2014 | A        |   
1     | 06/01/2014 | A        |   X
2     | 01/01/2014 | B        |   
2     | 07/01/2014 | B        |   
2     | 14/01/2014 | F        |   
2     | 21/01/2014 | A        |   
2     | 31/01/2014 | A        |   
2     | 06/01/2014 | D        |   

我需要在标记列中放置一个给定ref的位置,例如: 1,和给定的一组产品,例如A,B,C日期相隔7天。

e.g。对于ref 1

ex1:01/01/2014 | A是在ex2的7天之内 ex2:07/01/2014 | B在ex1和ex3的7天内 ex3:14/01/2014 | C在ex2和ex4的7天内 ex4:21/01/2014 | A是在ex3的7天内

所以你可以看到它们不是在7天之内,而是在7天之内相互串联。

另一个复杂因素是除非字符串包含A,B和C,否则不应标记任何内容!

我想你可以理解为什么我在努力解决这个问题,非常感谢任何建议!

由于

3 个答案:

答案 0 :(得分:1)

样本表

CREATE TABLE #TEMP(REF INT,[DATE] DATE,PRODUCT VARCHAR(10))

INSERT INTO #TEMP
SELECT 1     , '01/01/2014' , 'A' 
UNION ALL       
SELECT 1     , '01/07/2014' , 'B'   
UNION ALL      
SELECT 1     , '01/14/2014' , 'C'   
UNION ALL      
SELECT 1     , '01/21/2014' , 'A'  
UNION ALL       
SELECT 1     , '01/31/2014' , 'A' 
UNION ALL        
SELECT 1     , '01/06/2014' , 'A'  
UNION ALL         
SELECT 2     , '01/01/2014' , 'B'  
UNION ALL       
SELECT 2     , '01/07/2014' , 'B' 
UNION ALL        
SELECT 2     , '01/14/2014' , 'F'
UNION ALL           
SELECT 2     , '01/21/2014' , 'A' 
UNION ALL           
SELECT 2     , '01/31/2014' , 'A'  
UNION ALL          
SELECT 2     , '01/06/2014' , 'D'  

QUERY

;WITH CTE AS
(
    SELECT ROW_NUMBER() OVER(ORDER BY (SELECT(0)))RNO, *
    FROM #TEMP  
)
SELECT C1.REF,C1.[DATE],C1.PRODUCT,
CASE WHEN  DATEDIFF(DAY,C2.[DATE],C1.[DATE]) BETWEEN -7 AND 7
    AND  C1.PRODUCT IN('A','B','C')
    OR DATEDIFF(DAY,C2.[DATE],C1.[DATE]) IS NULL THEN 'X' ELSE NULL END MARK
FROM CTE C1
LEFT JOIN CTE C2 ON C1.RNO=C2.RNO+1 AND C1.REF=C2.REF

答案 1 :(得分:0)

这是标记你想要的记录......

DECLARE @prods TABLE (prod VARCHAR(10), prevprod VARCHAR(10), nextprod VARCHAR(10) )
INSERT INTO @prods (prod , prevprod , nextprod ) 
      SELECT 'A','C','B' 
UNION SELECT 'B','A','C' 
UNION SELECT 'C','B','A'

DECLARE @dates TABLE (REF INT,[DATE] DATE,PRODUCT VARCHAR(10))
INSERT INTO @dates
          SELECT 1, '01/01/2014' , 'A' 
UNION ALL SELECT 1, '01/07/2014' , 'B'   
UNION ALL SELECT 1, '01/14/2014' , 'C'   
UNION ALL SELECT 1, '01/21/2014' , 'A'  
UNION ALL SELECT 1, '01/31/2014' , 'A' 
UNION ALL SELECT 1, '01/06/2014' , 'A'  
UNION ALL SELECT 2, '01/01/2014' , 'B'  
UNION ALL SELECT 2, '01/07/2014' , 'B' 
UNION ALL SELECT 2, '01/14/2014' , 'F'
UNION ALL SELECT 2, '01/21/2014' , 'A' 
UNION ALL SELECT 2, '01/31/2014' , 'A'  
UNION ALL SELECT 2, '01/06/2014' , 'D'  

SELECT x1.* , 'X' = CASE WHEN EXISTS(
  SELECT * FROM @dates AS x2 
  INNER JOIN @prods AS p2 ON p2.prod = x2.PRODUCT
  WHERE x1.REF = x2.REF AND 
  (
   ( DATEDIFF(day, x1.DATE , x2.DATE) BETWEEN  0 AND 7  AND p1.prod = p2.prevprod )
   OR
   ( DATEDIFF(day, x1.DATE , x2.DATE) BETWEEN -7 AND 0  AND p1.prod = p2.nextprod )
  )
) THEN 'X' ELSE '' END
FROM @dates AS x1
LEFT OUTER JOIN @prods AS p1 ON p1.prod = x1.PRODUCT

原始示例的结果:

REF         DATE       PRODUCT    X
----------- ---------- ---------- ----
1           2014-01-01 A          X
1           2014-01-07 B          X
1           2014-01-14 C          X
1           2014-01-21 A          X
1           2014-01-31 A          
1           2014-01-06 A          X
2           2014-01-01 B          
2           2014-01-07 B          
2           2014-01-14 F          
2           2014-01-21 A          
2           2014-01-31 A          
2           2014-01-06 D          

现在,正如DominicA建议的那样,如果你改变了

UNION ALL SELECT 1,'01 / 14/2014','C'

UNION ALL SELECT 3,'01 / 14/2014','C'
你会得到这个结果

REF         DATE       PRODUCT    X
----------- ---------- ---------- ----
1           2014-01-01 A          X
1           2014-01-07 B          X
3           2014-01-14 C          
1           2014-01-21 A          
1           2014-01-31 A          
1           2014-01-06 A          X
2           2014-01-01 B          
2           2014-01-07 B          
2           2014-01-14 F          
2           2014-01-21 A          
2           2014-01-31 A          
2           2014-01-06 D          

答案 2 :(得分:0)

现在我明白了你想要的......

原始列表:

    DECLARE @prods TABLE (prod VARCHAR(10), prevprod VARCHAR(10), nextprod VARCHAR(10) )
    INSERT INTO @prods (prod , prevprod , nextprod ) 
          SELECT 'A','C','B' 
    UNION SELECT 'B','A','C' 
    UNION SELECT 'C','B','A'

    DECLARE @dates TABLE (REF INT,[DATE] DATE,PRODUCT VARCHAR(10))

    INSERT INTO @dates
              SELECT 1, '01/01/2014' , 'A' 
    UNION ALL SELECT 1, '01/07/2014' , 'B'   
    UNION ALL SELECT 1, '01/14/2014' , 'C'   
    UNION ALL SELECT 1, '01/21/2014' , 'A'  
    UNION ALL SELECT 1, '01/31/2014' , 'A' 
    UNION ALL SELECT 1, '01/06/2014' , 'A'  
    UNION ALL SELECT 2, '01/01/2014' , 'B'  
    UNION ALL SELECT 2, '01/07/2014' , 'B' 
    UNION ALL SELECT 2, '01/14/2014' , 'F'
    UNION ALL SELECT 2, '01/21/2014' , 'A' 
    UNION ALL SELECT 2, '01/31/2014' , 'A'  
    UNION ALL SELECT 2, '01/06/2014' , 'D'  

;WITH list AS (
  SELECT 
      REF1 = x1.REF, DATE1 = x1.DATE, PRODUCT1 = x1.PRODUCT
    , REF2 = x2.REF, DATE2 = x2.DATE, PRODUCT2 = x2.PRODUCT
    , REF3 = x3.REF, DATE3 = x3.DATE, PRODUCT3 = x3.PRODUCT
  FROM @dates AS x1 
  INNER JOIN @prods AS p1 ON p1.prod = x1.PRODUCT
  INNER JOIN @dates AS x2 ON x1.REF = x2.REF AND x2.PRODUCT = p1.nextprod AND DATEDIFF(day, x1.DATE , x2.DATE) BETWEEN  1 AND 7
  INNER JOIN @prods AS p2 ON p2.prod = x2.PRODUCT
  INNER JOIN @dates AS x3 ON x2.REF = x3.REF AND x3.PRODUCT = p2.nextprod AND DATEDIFF(day, x2.DATE , x3.DATE) BETWEEN  1 AND 7
)
, list2 as (
  SELECT z.* , 'X' = CASE WHEN EXISTS(
      SELECT * 
      FROM list AS x
      WHERE 
        ( z.REF = x.REF1 AND z.DATE = x.DATE1 AND z.PRODUCT = x.PRODUCT1 )
        OR
        ( z.REF = x.REF2 AND z.DATE = x.DATE2 AND z.PRODUCT = x.PRODUCT2 )
        OR
        ( z.REF = x.REF3 AND z.DATE = x.DATE3 AND z.PRODUCT = x.PRODUCT3 )
    ) THEN 'X' ELSE '' END
  FROM @dates AS z
)

SELECT x.REF, X.DATE, X.PRODUCT, X = CASE WHEN x.X = '' AND EXISTS(
  SELECT * 
  FROM @prods AS p 
  INNER JOIN list2 AS x4 ON   x4.X = 'X'
                          AND x4.REF = x.REF 
                          AND x4.PRODUCT = p.prevprod
                          AND DATEDIFF(day, x4.DATE , x.DATE) BETWEEN  1 AND 7
  WHERE p.prod = x.PRODUCT
) THEN 'X' ELSE x.X END
FROM list2 AS x
INNER JOIN @prods AS p ON p.prod = x.PRODUCT

结果是:

REF         DATE       PRODUCT    X
----------- ---------- ---------- ----
1           2014-01-01 A          X
1           2014-01-07 B          X
1           2014-01-14 C          X
1           2014-01-21 A          X
1           2014-01-31 A          
1           2014-01-06 A          X
2           2014-01-01 B          
2           2014-01-07 B          
2           2014-01-21 A          
2           2014-01-31 A          

现在,正如DominicA建议的那样,如果你改变了

UNION ALL SELECT 1, '01/14/2014' , 'C'

UNION ALL SELECT 3, '01/14/2014' , 'C'

你会得到这些结果:

REF         DATE       PRODUCT    X
----------- ---------- ---------- ----
1           2014-01-01 A          
1           2014-01-07 B          
3           2014-01-14 C          
1           2014-01-21 A          
1           2014-01-31 A          
1           2014-01-06 A          
2           2014-01-01 B          
2           2014-01-07 B          
2           2014-01-21 A          
2           2014-01-31 A          

如果您改为

UNION ALL SELECT 1, '01/21/2014' , 'A'

UNION ALL SELECT 3, '01/21/2014' , 'A'

你会得到这些结果:

REF         DATE       PRODUCT    X
----------- ---------- ---------- ----
1           2014-01-01 A          X
1           2014-01-07 B          X
1           2014-01-14 C          X
3           2014-01-21 A          
1           2014-01-31 A          
1           2014-01-06 A          X
2           2014-01-01 B          
2           2014-01-07 B          
2           2014-01-21 A          
2           2014-01-31 A