简化某个SQL Server查询

时间:2014-06-06 22:37:27

标签: sql-server

我想计算两个表的内容增量 - @i@j

DECLARE @i TABLE (
    [Id] [int] NOT NULL,
    [Modified] [int] NOT NULL
)

DECLARE @j TABLE (
    [Id] [int] NOT NULL,
    [Code] [char](1) NOT NULL,
    [Exported] [int] NOT NULL
)

delta应该只包含一列 - Id,并按以下方式计算:

  1. 结果中的任何Id来自@i@j或两者(即FULL JOIN
  2. 如果@i.Id中找不到@j或找不到@j.Code = 'D'@i.Id,则会@i.Id。{/ li>
  3. 如果在@j@j.Exported < @i.Modified中找到@i.Id,则会@j.Code <> 'D'。{/ li>
  4. 如果在@j.Id中找不到@i@j.Id,则会SELECT COALESCE(i.Id, j.Id) Id FROM @i i FULL JOIN (SELECT * FROM @j WHERE Code <> 'D') j ON i.Id = j.Id WHERE j.Exported IS NULL OR i.Modified IS NULL OR (j.Exported < i.Modified)
  5. 这是我附带的SQL:

    INSERT INTO @i VALUES (1,0),(2,0)
    INSERT INTO @j VALUES (1,'D',1),(2,'C',1)
    

    这是SQL works great

    例如:

    1

    增量为SELECT COALESCE(i.Id, j.Id) Id FROM @i i FULL JOIN @j j ON Code <> 'D' AND i.Id = j.Id WHERE j.Exported IS NULL OR i.Modified IS NULL OR (j.Exported < i.Modified)

    我的问题是 - 我可以通过消除嵌套的select语句来简化这个SQL查询吗?

    我试过这个:

    1

    但它产生两行 - 1Id。请参阅here

    修改

    伙计们,我故意提供一个非常简单的例子来证明这个问题。实际上,查询更复杂,键实际上是复合键,delta的结果不是简单的{{1}},而是更多。但问题是一样的。

2 个答案:

答案 0 :(得分:0)

您应该能够使用案例陈述来评估这些条件。我不确定我是否涵盖了所有的边缘情况,但这里的逻辑很快转换成一个案例:

DECLARE @i TABLE (
    [Id] [int] NOT NULL,
    [Modified] [int] NOT NULL
)

DECLARE @j TABLE (
    [Id] [int] NOT NULL,
    [Code] [char](1) NOT NULL,
    [Exported] [int] NOT NULL
)

INSERT INTO @i values (1,0)
insert into @i values (2,0)
INSERT INTO @j VALUES (1,'D',1)
insert into @j values (2,'C',1)

--The delta should contain just one column - Id and be calculated like this:

--Any Id in the result is coming from @i or @j or both (i.e. FULL JOIN)
--If @i.Id is not found in @j or found, but @j.Code = 'D', then @i.Id is taken.
--If @i.Id is found in @j and @j.Exported < @i.Modified, then @i.Id is taken.
--If @j.Code <> 'D' and @j.Id is not found in @i, then @j.Id is taken.



select  [Id] =  max(case 
                    when j.Code = 'D' then i.Id
                    when j.Id is not null and j.Exported < i.Modified then i.Id
                    when j.Code <> 'D' and i.Id is null then j.Id
                    else -1 -- ??
                end)

from    @i i 
left
join    @j j on i.Id = j.Id

答案 1 :(得分:0)

了解案例陈述不适合您的申请,我可以建议:

-- 1. Any Id in the result is coming from @i or @j or both (i.e. FULL JOIN)
-- 2. If @i.Id is not found in @j or found, but @j.Code = 'D', then @i.Id is taken.
-- 3. If @i.Id is found in @j and @j.Exported < @i.Modified, then @i.Id is taken.
-- 4. If @j.Code <> 'D' and @j.Id is not found in @i, then @j.Id is taken

SELECT COALESCE(i.Id, j.Id) Id
FROM @i AS i
FULL JOIN @j AS j ON i.Id = j.Id
WHERE 
  (i.Id IS NOT NULL AND
  ( -- #2
    j.Id IS NULL OR j.Code = 'D' OR
    -- #3
   (j.Exported IS NOT NULL AND j.Exported < i.Modified))
  )
  -- #4
  OR (i.Id IS NULL AND j.Code <> 'D');