SQL,在计算两次之间的差异时插入表

Posted

技术标签:

【中文标题】SQL,在计算两次之间的差异时插入表【英文标题】:SQL, insert into table while calculating difference between two times 【发布时间】:2020-01-23 09:54:22 【问题描述】:

我目前正在使用 fullcalendar 制作一个简单的日历。我的数据库有三个日期时间:

start 
end
total

我想要的是程序,因为它插入日期,以计算开始和结束之间的差异并将其添加到总数中。这是我的插入 SQL 代码:

我在 mysql 中使用 InnoDB。

session_start();

include_once './conexao.php';

$dados = filter_input_array(INPUT_POST, FILTER_DEFAULT);

//Converter a data e hora do formato brasileiro para o formato do Banco de Dados
$data_start = str_replace('/', '-', $dados['start']);
$data_start_conv = date("Y-m-d H:i:s", strtotime($data_start));

$data_end = str_replace('/', '-', $dados['end']);
$data_end_conv = date("Y-m-d H:i:s", strtotime($data_end));

$query_event = "INSERT INTO events (title, name, color, start, end, total) "
        . "VALUES (:title, :name, :color, :start, :end) "
        . "SELECT DATEDIFF(':start', ':end') AS total";

$insert_event = $conn->prepare($query_event);
$insert_event->bindParam(':title', $dados['title']);
$insert_event->bindParam(':name', $dados['name']);
$insert_event->bindParam(':color', $dados['color']);
$insert_event->bindParam(':start', $data_start_conv);
$insert_event->bindParam(':end', $data_end_conv);

if ($insert_event->execute()) 
    $retorna = ['sit' => true, 'msg' => '<div class="alert alert-success" role="alert">Evento inserido com sucesso!</div>'];
    $_SESSION['msg'] = '<div class="alert alert-success" role="alert">Evento inserido com sucesso!</div>';
 else 
    $retorna = ['sit' => false, 'msg' => '<div class="alert alert-danger" role="alert">Erro: Evento não foi inserido com sucesso!</div>'];



header('Content-Type: application/json');
echo json_encode($retorna);```


【问题讨论】:

运行这段代码会发生什么?你有错误吗? 【参考方案1】:

我可以看到您一定遇到了 SQL 语法错误 - 您不能在同一个查询中使用 INSERT...VALUESINSERT...SELECT 语法 - 您必须使用其中一个。但是这里不需要SELECT,您可以将 DATEDIFF 函数作为值之一。传递给 DATEDIFF 的参数也不需要引号。

您也不能在 PDO 中使用相同的参数名称两次。

我认为这应该会更好(虽然我无法测试它,显然):

$query_event = "INSERT INTO events (title, name, color, start, end, total) "
        . "VALUES (:title, :name, :color, :start, :end, DATEDIFF(:start2, :end2))";

$insert_event = $conn->prepare($query_event);
$insert_event->bindParam(':title', $dados['title']);
$insert_event->bindParam(':name', $dados['name']);
$insert_event->bindParam(':color', $dados['color']);
$insert_event->bindParam(':start', $data_start_conv);
$insert_event->bindParam(':end', $data_end_conv);
$insert_event->bindParam(':start2', $data_start_conv);
$insert_event->bindParam(':end2', $data_end_conv);

附:如果你在运行代码时还有其他问题,你需要具体解释一下,因为你一开始没有提到。

【讨论】:

我无法使用此代码插入任何内容,并且我没有收到任何错误。它可能与我管理日历的 JS 脚本有关。此代码:pastebin.com/pCawrQQP 能够插入数据,是我在尝试计算差异之前所做的代码 如果你认为错误在JS端,你需要调试JS端,检查是否甚至触发了PHP执行。你没有显示任何这些,所以我无法帮助你。但是这个答案应该可以解决 PHP 的问题。也许您应该使用 PostMan 之类的工具对 PHP 部分进行单元测试以生成 HTTP 请求,然后一旦它工作正常,您就可以修复客户端代码以使其正确生成自己的请求。 @Rui 如果你认为这个查询仍然有错误,那么你需要调试它。确保 PDO 设置为在发生错误时抛出异常(请参阅php.net/manual/en/pdo.error-handling.php)并确保 PHP 设置为记录和/或回显错误(请参阅stackify.com/php-error-logs-guide)。设置它,然后再次运行代码,看看它报告了什么。这样你可能对如何开始修复它有一个更好的想法。 P.S.无论如何,我不相信你真的需要这个total 专栏。可以使用您已经存储的“开始”和“结束”值随时计算这样的值。关系数据库理论通常建议您不要存储可以使用其他存储值计算的值 - 相反,您只需在 SELECT 查询中按需执行计算,只要您想查看该数据。 (唯一的例外是计算运行速度很慢,尤其是对于大型数据集。但这不应该是一个大问题。) 感谢这里给我的时间,我肯定会设置错误处理,因为我确实忘记这样做了。我还将进一步研究 SELECT 查询,看看是否可以使用 html 表进行计算【参考方案2】:

不要在一个插入语句中混合使用 Values 子句和 Select 子句。 你有两种选择:

$query_event = "INSERT INTO events (title, name, color, start, end, total) "
        . "VALUES (:title, :name, :color, :start, :end, DATEDIFF(':start', ':end')) "
$query_event = "INSERT INTO events (title, name, color, start, end, total) "
        . "SELECT :title, :name, :color, :start, :end, DATEDIFF(':start', ':end') AS total from dual";

【讨论】:

您好,感谢您的代码。我使用了第二个,它可以插入,但是当类型设置为 int 或空字符串时,它会将总计打印为 0。这可能与我的日期格式有关?设置如下:YYYY-MM-DD HH:MM:SS Datediff 给出天数。这可以是 0。您还可以使用 timediff,它以小时为单位给出开始和结束之间的时间 没错,但是假设 start = 2020-02-10 和 end = 2020-02-15,时间差应该是 5 或 -5,具体取决于您如何设置代码。这对我来说不是这种情况,无论两个日期之间的长度差异如何,由于某种原因,结果总是为 0。我会进一步调查,谢谢你的时间!【参考方案3】:

[编辑] 我认为这可以做到:

INSERT INTO events (title, name, color, start, end, total) 
SELECT :title, :name, :color, t.start, t.end, DATEDIFF(t.start, t.end) )
FROM ( SELECT :start, :end) AS t

但您需要尝试确定。

【讨论】:

您不能在 PDO 中两次使用相同的参数名称...另外,您不打算解释一下为什么您的版本更好吗?这将是一个更有用的答案。 @ADyson 啊sh*,最近PL做的太多了,完全忘记了,谢谢。 @ADyson 比 ?操作请求?它应该工作;您的答案 ?我不认为它更好,只是不同;)我在 SQL 端放了更多逻辑,你把它放在 PHP 上:并没有太大的区别。 (而且我没有看到任何真正有用的大答案) 比 OP 的代码更好 - 即解释您所做的更改以及为什么它可以解决问题。代码转储本身对那些一开始不理解他们的错误的人没有用......我在评论你的原始版本,不要忘记,而不是你改变的 SQL。您的代码是否比我的“更好”由 OP 决定,而不是我。我说的是你帖子的整体质量。我试图通过添加一些解释性说明来鼓励您使其更有用 - 这并不是为了对其本身进行简单的批评。 感谢@Blag 的评论,这段代码和Adyson 有同样的问题,可能与我设置JS 代码的方式有关,我会进一步研究。

以上是关于SQL,在计算两次之间的差异时插入表的主要内容,如果未能解决你的问题,请参考以下文章

找出两次之间的差异

在PHP中获取两次之间的时间差[重复]

在 SQL 中搜索两次之间的变量

如何计算两个时间字符串之间的时间间隔

两次之间的时间差(分钟)

我如何使用 mysql 选择查询在“x 小时 y 分钟 z 秒”之类的词中获得 2 次之间的差异