0

所以,我发现自己处于不得不玩 DBA 的令人羡慕的位置(我通常是系统管理员),而我遇到的问题是:

我有两张桌子,一张是人们到达现场时记录的,另一张是他们离开时记录的。

理想情况下,两个表之间的数据应该刚好匹配,并且我应该能够在它们上使用内部 JOIN 来获得我想要的视图。但我们所看到的是,人们并没有像他们应该的那样办理入住和退房手续。所以,这意味着我可以让一些人在签入表中,而这些人不会出现在结账表中,反之亦然。

我已经尝试在两个表之间进行左连接,但这仍然会重复输出中 checkin 表的一些行......

SELECT a.name,a.timein,a.signature,b.timeout,b.signature 
FROM check_in a
LEFT JOIN check_out b ON a.datein = b.dateout
WHERE a.datein = '2019-01-28';

我想要的是一个查询,它可以让我从 checkin 表中获取今天日期的所有行,并从今天日期的同一结果集中从 checkout 表中提取所有行。

有什么办法可以做到这一点,还是我只需要使用两个查询,直到我可以将这些数据存储在一个表中?

4

4 回答 4

2

听起来您想要一个完整的外部连接,但您需要连接表之间的公共标识符。在您加入日期的那一刻,这将加入该日期的 check_in 中的所有行,以及该日期的 check_out 中的所有行(即,如果您有 5 人在示例日签入并签出,那么您d 得到 25 行返回)。所以假设name是标识符,你会做类似的事情:

SELECT a.name,a.timein,a.signature,b.timeout,b.signature, b.name 
FROM check_in a
FULL OUTER JOIN check_out b ON a.name = b.name
    and a.datein = b.dateout
WHERE a.datein = '2019-01-28' 
OR b.dateout = '2019-01-28';

我已将结果包含b.name在结果中,因为如果有人已签出但未签出,那么您将无法获得a.name.

另一种选择可能是进行联合,因此请使用以下内容:

SELECT a.name,a.timein,a.signature,b.timeout,b.signature
FROM check_in a
LEFT OUTER JOIN check_out b ON a.name = b.name
    and a.datein = b.dateout
WHERE a.datein = '2019-01-28' 
UNION
SELECT co.name, '', '', co.timeout, co.signature
FROM check_out co
where not exists (SELECT 1 
    FROM check_in ci
    WHERE ci.name = co.name 
    AND ci.datein = co.dateout)
AND co.dateout = '2019-01-28'

因此,查询的上半部分将返回匹配项和那些有签入和签出的,以及那些签入但没有签出的,下半部分选择那些签出但没有匹配签入的,但是它返回第一列中的 check_out 名称,因此第 1 列将始终具有该名称。

然后你可以从那里得到你想要的花哨。

于 2019-01-29T03:54:17.453 回答
0

听起来您想要签入日期与签出日期匹配没有签入日期没有签出日期的行,所以我会编写如下查询:

SELECT a.name, a.timein, a.signature, b.timeout, b.signature
FROM check_in a, check_out b,
WHERE a.user = b.user
AND a.datein = ‘2019-01-28’
AND (a.datein = b.dateout OR a.datein IS NULL OR b.dateout IS NULL);
于 2019-01-29T03:19:37.710 回答
0

使用union all

select c.*
from ((select ci.name, ci.timein, ci.signature as in_signature,
              null as timeout, null as out_signature
       from check_in ci
       where ci.check_in = '2019-01-28'
      ) union all
      (select co.name, null, null,
              co.timeout, co.signature as out_signature
       from check_out co
       where ci.check_in = '2019-01-28'
      )
     ) c;

我强烈建议您不要使用join将数据组合在一起,因为这可能会增加行数。您将希望更好地了解数据中的内容,而无需将任一表中的行相乘。

于 2019-01-29T12:58:25.623 回答
0

只要至少有一个日期与您要查找的日期匹配,完全外连接将从check_in和中获取行。check_out一个简单OR的 inWHERE子句应该足以获得您想要的所有记录。

SELECT a.name, a.timein, a.signature, b.timeout, b.signature 
FROM check_in a
FULL OUTER JOIN check_out b
ON a.datein = b.dateout AND a.name = b.name
WHERE a.datein = '2019-01-28' OR b.dateout = '2019-01-28';
于 2019-01-29T03:56:30.870 回答