如果存在于一个表中,则选择记录,否则从另一个表中选择

时间:2015-07-13 19:33:51

标签: sql sql-server if-statement

我正在为报价撰写报告。报价表有一个副本来跟踪更改历史记录,因此每当有人更改报价表时,旧的值都会在此历史记录表中显示。

我想在名为Original Due Date的报告中添加一个字段,该字段将显示报价的原始截止日期。如果历史记录表中有记录,则应该从那里获得第一个截止日期。否则它应该从原始表中获得截止日期。

以下是我在表格中记录的一些示例。

表1:

|ID | Order  | Due Date   |
|1  | C1234  | 15/01/2000 |
|2  | C1235  | 15/02/2000 |
|3  | C1236  | 15/03/2000 |
|4  | C1237  | 15/04/2000 |

历史表:

|ID | Order  | Due Date   |
|1  | C1234  | 02/01/2000 |
|2  | C1234  | 05/01/2000 |
|3  | C1236  | 05/03/2000 |
|4  | C1236  | 07/03/2000 |

预期结果:

|ID | Order  | Original Due Date   |
|1  | C1234  | 02/01/2000          |
|2  | C1235  | 15/02/2000          |
|3  | C1236  | 05/03/2000          |
|4  | C1237  | 15/04/2000          |

这是我尝试过的代码,由于我的子查询返回的值超过1,因此无效。

 select case when exists (select 1 from quoteheader qh inner join quoteheaderhistory qhh on QH.QH_RecordID = QHH.QH_RecordID)
        then (select QHH.QH_RFQ_Date from quoteheader qh inner join quoteheaderhistory qhh on QH.QH_RecordID = QHH.QH_RecordID)
        else QH.QH_RFQ_Date
        end,
    * from quoteheader qh inner join quoteheaderhistory qhh
          on QH.QH_RecordID = QHH.QH_RecordID

5 个答案:

答案 0 :(得分:2)

这应该有效:

DECLARE @tblO TABLE(ID INT,[Order] VARCHAR(10),DueDate DATE);
INSERT INTO @tblO VALUES(1,'C1234','20000115'),(2,'C1235','20000215'),(3,'C1236','20000315'),(4,'C1237','20000415');

DECLARE @tblH TABLE(ID INT,[Order] VARCHAR(10),DueDate DATE);
INSERT INTO @tblH VALUES(1,'C1234','20000102'),(2,'C1234','20000105'),(3,'C1236','20000305'),(4,'C1236','20000307');

WITH MinHistoricalDates AS
(
    SELECT MIN(DueDate) AS MinHistDat,[order]
    FROM @tblH
    GROUP BY [order]
)
SELECT orig.ID 
      ,orig.[order]
      ,ISNULL(mhd.MinHistDat,orig.DueDate) AS DueDateResolved 
FROM @tblO AS orig
LEFT JOIN MinHistoricalDates AS mhd ON mhd.[order]=orig.[order]

答案 1 :(得分:1)

尝试:

select [Order],[DueDate] from quoteheader
where [Order] not in
(select [Order] from
(select [Order],MIN(DueDate) as DueDate
from quoteheaderhistory 
group by [Order]) a
)

union all

select [Order],MIN(DueDate) as DueDate
from quoteheaderhistory 
group by [Order]

尽管join答案可能对您有效,具体取决于您的数据

答案 2 :(得分:1)

以下是我在评论中谈到的内容:

DECLARE @A TABLE ([ID] INT, [Order] CHAR(5), [DueDate] DATE)
DECLARE @H TABLE ([ID] INT, [Order] CHAR(5), [DueDate] DATE)

INSERT INTO @A VALUES
(1, 'C1234', '01/15/2000'), 
(2, 'C1235', '02/15/2000'), 
(3, 'C1236', '03/15/2000'), 
(4, 'C1237', '04/15/2000')

INSERT INTO @H VALUES
(1, 'C1234', '01/02/2000'),
(2, 'C1234', '01/05/2000'),
(3, 'C1236', '03/05/2000'),
(4, 'C1236', '03/07/2000')

SELECT
    [header].[ID],
    [header].[Order],
    [DueDate] = ISNULL(MIN([history].[DueDate]), MIN([header].[DueDate]))
FROM
    @A [header]
    LEFT JOIN @H [history] ON [header].[Order] = [history].[Order]
GROUP BY
    [header].ID, [header].[Order];

编辑: Shnugo 的答案有更好的执行计划;跟那个一起去。

答案 3 :(得分:1)

或者,您也可以执行left join并使用MIN的窗口函数版本来实现您的结果:

select distinct
     t1.id,
     t1.[order],
     COALESCE(min(ht.Due_Date) OVER (partition by t1.[order] order by t1.id)
    ,min(t1.due_date) OVER (partition by t1.[order] order by t1.id)) as Original Due Date  
from table1 t1
left join history_table ht on ht.[Order] = t1.[Order];

SQL Fiddle Demo

答案 4 :(得分:0)

试试这个:

SELECT _order, min(due_date) as due_date
FROM history JOIN table1 USING (_order)
GROUP BY _order

此解决方案忽略了id,但您可以在获得适当的值后轻松生成。