Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 根据表B中的年龄计算从表A中选择行_Mysql_Sql - Fatal编程技术网

Mysql 根据表B中的年龄计算从表A中选择行

Mysql 根据表B中的年龄计算从表A中选择行,mysql,sql,Mysql,Sql,表1我们有身份证,出生日期,如1980年1月1日 表2我们有id和其他列 如果id小于20岁,如何从表2中获取所有行 我目前有: SELECT * FROM table2 WHERE id IN ( SELECT id FROM table1 WHERE TIMESTAMPDIFF(Year,DOB,curdate()) <= 20 ) 我的解决方案有效吗?用于MySQL SELECT table2.* FROM table1 JOIN table2 ON tab

表1我们有身份证,出生日期,如1980年1月1日 表2我们有id和其他列

如果id小于20岁,如何从表2中获取所有行

我目前有:

SELECT *
FROM table2
WHERE id IN (
    SELECT id
    FROM table1
    WHERE TIMESTAMPDIFF(Year,DOB,curdate()) <= 20
)
我的解决方案有效吗?

用于MySQL

SELECT table2.*
FROM table1
JOIN table2 ON table1.id = table2.id
WHERE table1.dob >= CURRENT_DATE - INTERVAL 20 YEAR

您最好在20年前计算一个日期,然后询问表数据是否在该日期之后。这意味着需要进行一次计算,而不是对表中的每一行进行计算。每次对行数据执行计算时,都意味着无法使用索引。如果对DOB进行索引,这将对性能造成灾难

TIMESTAMPDIFF不计算两个日期之间的年数,它提供了一年在两个日期的12月31日滚动的次数。这意味着要求12月31日和1月1日之间的差额将报告为1年,而事实上,根据时间的不同,只有一天或最多两天

SELECT id  
FROM table1 
where DOB > DATE_SUB(CURDATE(), INTERVAL 20 YEAR)
就个人而言,我使用join而不是IN,因为一旦您了解了模式,就很容易使用左连接来扩展它,以查找不存在的行或与模式匹配的行,但实际上查询优化器会重写IN和join以执行相同的行。有些数据库在IN中的性能很差,因为它们的执行方式与连接不同

SELECT * 
FROM 
  table1 t1
  INNER JOIN table2 t2
  ON t1.id = t2.id
where t1.DOB > DATE_SUB(CURDATE(), INTERVAL 20 YEAR)
Mech强调在生产代码中应避免选择*。这在很大程度上是一个相关的问题-始终只选择您需要的列有时如果dB为表编制了索引,并且您只需要索引中的列,那么使用select*将对性能造成影响,因为dB必须使用索引查找哪些行,然后再查找这些行。如果指定所需的列,它可以决定是否可以纯粹从索引中回答查询,以提高速度。我可以考虑使用SELECT*的唯一时间是在一个子查询中,优化器无论如何都会重写< /P>
始终为表添加别名并使用别名。如果以后向其中一个表中添加与另一个表中的列同名的列,则可以防止查询中断。虽然添加东西通常不是问题,也不会导致bug和崩溃,但如果查询只是从join b.中选择名称。。只有表a有一个名称列,如果将名称列添加到b中,它将开始崩溃。指定一个.name可以防止这种情况的发生。从历史上看,MySQL实现EXISTS的效率比中的更高。因此,我建议:

SELECT t2.*
FROM table2 t2
WHERE EXISTS (SELECT 1
              FROM table1 t1
              WHERE t1.id = t2.id AND
                    TIMESTAMPDIFF(Year, t1.DOB, curdate()) <= 20
             );
这大概就是您想要的逻辑,索引可以利用它


我建议不要使用联接,因为结果集中没有重复行的风险。您的问题没有指定id在表1中是唯一的,因此重复是一种风险。即使没有副本,在许多情况下,这也将具有最佳性能。

切勿使用*。始终定义要选择的列。我的解决方案是否有效?否。使用日期数据类型存储日期这会鼓励在select语句中使用*的不良做法。有关详细信息,请阅读。@Mech我的一些程序使用用户配置的报告服务,该服务可能需要在表中存在的任何列中使用。此外,任何现在不存在但将来可能出现的列,这可能在没有代码更正的情况下工作,同时报告子系统没有任何反馈。。。除了选择所有现有列,您是否可以提供其他解决方案?宣布任何规则都是绝对真理是不好的做法。@Mech你真的认为所有提供的解决方案都是由OPs应用的,没有任何版本吗?向OP指出一个可能存在的问题,让他考虑或忽略它。@Mech我认为你纯粹基于选择*的否决票是不必要的。OP没有给出表中有哪些列的任何指示,他最终将如何处理这个查询取决于他自己,包括任何后果。你已经直接向他表明了你的观点,没有理由对每一个提到select*的sql问题/答案都进行向下投票。在单个表子查询中选择*可能是可以接受的,例如,因为*而放弃投票没有意义。它是提供解决方案的Sql标准。由于所使用的方法在他的查询中没有提供列,因此Akina的解决方案是完全有效的
t1.DOB <= curdate() - interval 20 year