比较表并获取非匹配值

时间:2015-12-09 13:34:31

标签: tsql sql-server-2012

我对SQL很陌生,我无法让它工作我在下面有这两个表

Table A                                 Table B
    _________________               _________________
    | A   | 2015-10-4               | B   | 2015-11-6
    | B   | 2015-11-4               | C   | 2015-05-4
    | C   | 2015-05-6               | D   | 2015-05-8
    | D   | 2015-05-7               | C   | 2015-05-5

我正在尝试编写一个存储过程,它将从表B中获取日期小于表A的所有字母以及表B中不存在的任何字母。

这是我到目前为止所拥有的

    SELECT      *
    FROM        A q JOIN 
                B c ON q.Letter = c.Letter AND q.Date > c.Date OR c.Letter IS NULL

这会返回C,但我也不能让它返回A.我试图加入并比较表格仍然令人困惑。

我不想要重复的行,我期望的结果会返回

| A   | 2015-10-4 
| C   | 2015-05-6

修改

我现在遇到一个问题,如果我有这样的案例

        Table A                           Table B
    _________________               _________________
    | A   | 2015-10-4               | B   | 2015-11-6
    | B   | 2015-11-4               | C   | 2015-05-4
    | C   | 2015-05-6               | D   | 2015-05-8
    | D   | 2015-05-7               | C   | 2015-05-5
                                    | C   | 2015-05-7

由于某种原因,它仍然会返回C.使用a.date > max(b.date)不起作用,因为max不能以这种方式使用。我想假设最大日期可以是表B中表格中的任何位置。

所以现在我的新结果将是

| A   | 2015-10-4 

但我仍然得到A和C.

2 个答案:

答案 0 :(得分:3)

您应该使用LEFT JOIN

SELECT DISTINCT A.letter, A.[Date]
FROM dbo.TableA A
LEFT JOIN dbo.TableB B
    ON A.letter = B.letter
WHERE B.[Date] < A.[Date] OR B.letter IS NULL;

<强>更新

你应该已经解释了你的要求:“从表B中获取每个日期都小于......的所有字母。”

SELECT DISTINCT A.letter, A.[Date]
FROM dbo.TableA A
LEFT JOIN (SELECT letter, MAX([Date]) [Date]
           FROM dbo.TableB
           GROUP BY letter) B
    ON A.letter = B.letter
WHERE B.[Date] < A.[Date] OR B.letter IS NULL;

答案 1 :(得分:0)

我会选择UNION / UNION ALL,以便获得第一个条件的结果子集+第二个条件的结果子集。 类似的东西应该做的工作:

sqlite> create table A (letter, my_date);
sqlite> create table B (letter, my_date);
sqlite> insert into A values ('A', '2015-10-04');
sqlite> insert into A values ('B', '2015-11-04');
sqlite> insert into A values ('C', '2015-05-06');
sqlite> insert into A values ('D', '2015-05-07');
sqlite> insert into B values ('B', '2015-11-06');
sqlite> insert into B values ('C', '2015-05-04');
sqlite> insert into B values ('D', '2015-05-08');
sqlite> insert into B values ('C', '2015-05-05');
A           2015-10-04
sqlite> select B.* from A, B where A.letter = B.letter and B.my_date < A.my_date UNION ALL select A.* from A where not exists (select 1 from B where B.letter=A.letter);
letter      my_date
----------  ----------
C           2015-05-04
C           2015-05-05
A           2015-10-04