数据库查询 returns 一个查询为负数,另一个为正数 - 不知道为什么
Database query returns minus number for one query and positive number for another - don't know why
我正在使用以下 NODE js 代码来 运行 时钟。对于一个特定的用户,似乎这是一个今天才出现的问题,这个特定的用户 (OPID 7) 被告知他已经工作 minus 时间,而其他用户显示他们的正确正时间工作时间?用户的opid是7
The tabular data is here,但我很困惑,因为我看不出 OPID 7 和 OPID 3 或 5 之间有任何区别...
firebird.attach(options, function(err, db) {
if(err) throw err;
app.get('/', (req, res) => {
db.query('SELECT opid, name FROM TXOPS WHERE OPID NOT IN (1, -1, 2, 9, 10, 13, 14)', function(err, rows) {
if(err) throw err;
res.render('index', { operators: rows });
});
})
app.get('/clock/:id', (req, res) => {
if(req.params.id) {
db.query('SELECT opid, name FROM TXOPS WHERE OPID = ' + req.params.id, function(err, operator_row = []) {
if(operator_row.length === 1)
{
var clockedIn = false;
db.query('SELECT FIRST 1 * FROM TXATTENDETXNTS WHERE OPID = ' + req.params.id + ' AND DATETIME >= \'' + moment().startOf('day').format('YYYY-MM-DD HH:mm:ss') + '\' ORDER BY DATETIME DESC', function(err, last_row) {
console.log(last_row);
if(err) throw err;
if(last_row.length === 1 && last_row[0].ETXNTTYPE === 0) clockedIn = true;
if(clockedIn)
{
db.query('SELECT FIRST 10 * FROM TXATTENDETXNTS WHERE OPID = ' + req.params.id + ' AND DATETIME >= \'' + moment().startOf('day').format('YYYY-MM-DD HH:mm:ss') + '\'', function(err, today_rows) {
totalMinutes = 0;
console.log(today_rows);
today_rows.push({ DATETIME: moment().format('YYYY-MM-DD HH:mm:ss')});
splitRows = today_rows.reduce(function(result, value, index, array) {
if (index % 2 === 0)
result.push(array.slice(index, index + 2));
return result;
}, []);
splitRows.forEach(pair => {
totalMinutes += Math.round(moment.duration(moment(pair[1].DATETIME).diff(moment(pair[0].DATETIME))).asMinutes());
});
console.log(totalMinutes);
minuteString = null;
hours = 0;
remainingMinutes = 0;
if(totalMinutes > 60)
{
hours = Math.floor(totalMinutes / 60);
remainingMinutes = totalMinutes - (hours * 60);
}
if(hours > 0 && remainingMinutes > 0)
{
minuteString = hours + ' hours and ' + remainingMinutes + ' minutes'
}
else if(hours > 0 && remainingMinutes === 0)
{
minuteString = hours + ' hours';
}
else {
minuteString = totalMinutes + ' minutes';
}
res.render('clock', { operator: operator_row[0], working_string: minuteString, clockedIn: clockedIn });
});
}
else
{
res.render('clock', {operator: operator_row[0], clockedIn: clockedIn})
}
});
}
});
}
})
app.get('/clock-in/:id', (req, res) => {
db.query('SELECT opid, name FROM TXOPS WHERE OPID = ' + req.params.id, function(err, rows) {
if(rows.length === 0)
{
res.render('error');
}
// Check if he's already clocked in
db.query('SELECT FIRST 1 OPID FROM TXATTENDETXNTS WHERE OPID = ' + req.params.id + ' ORDER BY ATTENDETXNTID DESC', function(err, rows) {
if(err) throw err;
if(rows.length === 1 && rows[0].ETXNTTYPE == 0)
{
res.render('error');
}
else
{
db.query('SELECT FIRST 1 ATTENDETXNTID FROM TXATTENDETXNTS ORDER BY ATTENDETXNTID DESC', function(err, rows) {
lastID = 0;
if(rows.length === 1)
{
lastID = rows[0].ATTENDETXNTID;
}
db.query('INSERT INTO TXATTENDETXNTS (ATTENDETXNTID, OPID, DATETIME, ETXNTTYPE, SCANNEDSTR, BRANCHID, CHANGED_FLAG, DEPTID) VALUES (' + (lastID + 1) + ','+ req.params.id +', \'' + moment().format('YYYY-MM-DD HH:mm:ss') + '\', 0, null, 1, 1, 0)', function(err, rows) {
if(err) throw err;
res.render('success');
client.publish('timeclock'+ req.params.id, 'clocked in');
});
});
}
});
});
})
app.get('/clock-out/:id', (req, res) => {
db.query('SELECT opid, name FROM TXOPS WHERE OPID = ' + req.params.id, function(err, rows) {
if(rows.length === 0)
{
res.render('error');
}
// Check if he's already clocked out
db.query('SELECT FIRST 1 OPID FROM TXATTENDETXNTS WHERE OPID = ' + req.params.id + ' ORDER BY ATTENDETXNTID DESC', function(err, rows) {
if(err) throw err;
if(rows.length === 1 && rows[0].ETXNTTYPE == 1)
{
res.render('error');
}
else
{
db.query('SELECT FIRST 1 ATTENDETXNTID FROM TXATTENDETXNTS ORDER BY ATTENDETXNTID DESC', function(err, rows) {
lastID = 0;
if(rows.length === 1)
{
lastID = rows[0].ATTENDETXNTID;
}
db.query('INSERT INTO TXATTENDETXNTS (ATTENDETXNTID, OPID, DATETIME, ETXNTTYPE, SCANNEDSTR, BRANCHID, CHANGED_FLAG, DEPTID) VALUES (' + (lastID + 1) + ','+ req.params.id +', \''+ moment().format('YYYY-MM-DD HH:mm:ss') +'\', 1, null, 1, 1, 0)', function(err, rows) {
if(err) throw err;
res.render('success');
client.publish('timeclock'+ req.params.id, 'clocked out');
});
});
}
});
});
})
app.get('/break-out/:id', (req, res) => {
db.query('SELECT opid, name FROM TXOPS WHERE OPID = ' + req.params.id, function(err, rows) {
if(rows.length === 0)
{
res.render('error');
}
// Check if he's already clocked out
db.query('SELECT FIRST 1 OPID FROM TXATTENDETXNTS WHERE OPID = ' + req.params.id + ' ORDER BY ATTENDETXNTID DESC', function(err, rows) {
if(err) throw err;
if(rows.length === 1 && rows[0].ETXNTTYPE == 1)
{
res.render('error');
}
else
{
db.query('SELECT FIRST 1 ATTENDETXNTID FROM TXATTENDETXNTS ORDER BY ATTENDETXNTID DESC', function(err, rows) {
lastID = 0;
if(rows.length === 1)
{
lastID = rows[0].ATTENDETXNTID;
}
db.query('INSERT INTO TXATTENDETXNTS (ATTENDETXNTID, OPID, DATETIME, ETXNTTYPE, SCANNEDSTR, BRANCHID, CHANGED_FLAG, DEPTID) VALUES (' + (lastID + 1) + ','+ req.params.id +', \''+ moment().format('YYYY-MM-DD HH:mm:ss') +'\', 1, null, 1, 1, 0)', function(err, rows) {
if(err) throw err;
res.render('success');
client.publish('timeclock'+ req.params.id, 'broke out');
});
});
}
});
});
})
})
数据库中的行 table 没有特定的顺序,它们的位置取决于插入的顺序,在数据页上可用 space 免费,插入时哪些页被锁定,和其他因素。此外,查询的结果可能会受到查询计划(包括索引使用)和 I/O 考虑因素的影响。
您的代码 - 特别是 SELECT FIRST 10 * FROM TXATTENDETXNTS ...
查询 - 假定较旧的行在较新的行之前返回。但是,这并不能保证,因此当较新的行出现在较旧的行之前时,您将得到负值。在为计算选择行时,您需要明确指定 ORDER BY
(例如 ORDER BY DATETIME
)。
我正在使用以下 NODE js 代码来 运行 时钟。对于一个特定的用户,似乎这是一个今天才出现的问题,这个特定的用户 (OPID 7) 被告知他已经工作 minus 时间,而其他用户显示他们的正确正时间工作时间?用户的opid是7
The tabular data is here,但我很困惑,因为我看不出 OPID 7 和 OPID 3 或 5 之间有任何区别...
firebird.attach(options, function(err, db) {
if(err) throw err;
app.get('/', (req, res) => {
db.query('SELECT opid, name FROM TXOPS WHERE OPID NOT IN (1, -1, 2, 9, 10, 13, 14)', function(err, rows) {
if(err) throw err;
res.render('index', { operators: rows });
});
})
app.get('/clock/:id', (req, res) => {
if(req.params.id) {
db.query('SELECT opid, name FROM TXOPS WHERE OPID = ' + req.params.id, function(err, operator_row = []) {
if(operator_row.length === 1)
{
var clockedIn = false;
db.query('SELECT FIRST 1 * FROM TXATTENDETXNTS WHERE OPID = ' + req.params.id + ' AND DATETIME >= \'' + moment().startOf('day').format('YYYY-MM-DD HH:mm:ss') + '\' ORDER BY DATETIME DESC', function(err, last_row) {
console.log(last_row);
if(err) throw err;
if(last_row.length === 1 && last_row[0].ETXNTTYPE === 0) clockedIn = true;
if(clockedIn)
{
db.query('SELECT FIRST 10 * FROM TXATTENDETXNTS WHERE OPID = ' + req.params.id + ' AND DATETIME >= \'' + moment().startOf('day').format('YYYY-MM-DD HH:mm:ss') + '\'', function(err, today_rows) {
totalMinutes = 0;
console.log(today_rows);
today_rows.push({ DATETIME: moment().format('YYYY-MM-DD HH:mm:ss')});
splitRows = today_rows.reduce(function(result, value, index, array) {
if (index % 2 === 0)
result.push(array.slice(index, index + 2));
return result;
}, []);
splitRows.forEach(pair => {
totalMinutes += Math.round(moment.duration(moment(pair[1].DATETIME).diff(moment(pair[0].DATETIME))).asMinutes());
});
console.log(totalMinutes);
minuteString = null;
hours = 0;
remainingMinutes = 0;
if(totalMinutes > 60)
{
hours = Math.floor(totalMinutes / 60);
remainingMinutes = totalMinutes - (hours * 60);
}
if(hours > 0 && remainingMinutes > 0)
{
minuteString = hours + ' hours and ' + remainingMinutes + ' minutes'
}
else if(hours > 0 && remainingMinutes === 0)
{
minuteString = hours + ' hours';
}
else {
minuteString = totalMinutes + ' minutes';
}
res.render('clock', { operator: operator_row[0], working_string: minuteString, clockedIn: clockedIn });
});
}
else
{
res.render('clock', {operator: operator_row[0], clockedIn: clockedIn})
}
});
}
});
}
})
app.get('/clock-in/:id', (req, res) => {
db.query('SELECT opid, name FROM TXOPS WHERE OPID = ' + req.params.id, function(err, rows) {
if(rows.length === 0)
{
res.render('error');
}
// Check if he's already clocked in
db.query('SELECT FIRST 1 OPID FROM TXATTENDETXNTS WHERE OPID = ' + req.params.id + ' ORDER BY ATTENDETXNTID DESC', function(err, rows) {
if(err) throw err;
if(rows.length === 1 && rows[0].ETXNTTYPE == 0)
{
res.render('error');
}
else
{
db.query('SELECT FIRST 1 ATTENDETXNTID FROM TXATTENDETXNTS ORDER BY ATTENDETXNTID DESC', function(err, rows) {
lastID = 0;
if(rows.length === 1)
{
lastID = rows[0].ATTENDETXNTID;
}
db.query('INSERT INTO TXATTENDETXNTS (ATTENDETXNTID, OPID, DATETIME, ETXNTTYPE, SCANNEDSTR, BRANCHID, CHANGED_FLAG, DEPTID) VALUES (' + (lastID + 1) + ','+ req.params.id +', \'' + moment().format('YYYY-MM-DD HH:mm:ss') + '\', 0, null, 1, 1, 0)', function(err, rows) {
if(err) throw err;
res.render('success');
client.publish('timeclock'+ req.params.id, 'clocked in');
});
});
}
});
});
})
app.get('/clock-out/:id', (req, res) => {
db.query('SELECT opid, name FROM TXOPS WHERE OPID = ' + req.params.id, function(err, rows) {
if(rows.length === 0)
{
res.render('error');
}
// Check if he's already clocked out
db.query('SELECT FIRST 1 OPID FROM TXATTENDETXNTS WHERE OPID = ' + req.params.id + ' ORDER BY ATTENDETXNTID DESC', function(err, rows) {
if(err) throw err;
if(rows.length === 1 && rows[0].ETXNTTYPE == 1)
{
res.render('error');
}
else
{
db.query('SELECT FIRST 1 ATTENDETXNTID FROM TXATTENDETXNTS ORDER BY ATTENDETXNTID DESC', function(err, rows) {
lastID = 0;
if(rows.length === 1)
{
lastID = rows[0].ATTENDETXNTID;
}
db.query('INSERT INTO TXATTENDETXNTS (ATTENDETXNTID, OPID, DATETIME, ETXNTTYPE, SCANNEDSTR, BRANCHID, CHANGED_FLAG, DEPTID) VALUES (' + (lastID + 1) + ','+ req.params.id +', \''+ moment().format('YYYY-MM-DD HH:mm:ss') +'\', 1, null, 1, 1, 0)', function(err, rows) {
if(err) throw err;
res.render('success');
client.publish('timeclock'+ req.params.id, 'clocked out');
});
});
}
});
});
})
app.get('/break-out/:id', (req, res) => {
db.query('SELECT opid, name FROM TXOPS WHERE OPID = ' + req.params.id, function(err, rows) {
if(rows.length === 0)
{
res.render('error');
}
// Check if he's already clocked out
db.query('SELECT FIRST 1 OPID FROM TXATTENDETXNTS WHERE OPID = ' + req.params.id + ' ORDER BY ATTENDETXNTID DESC', function(err, rows) {
if(err) throw err;
if(rows.length === 1 && rows[0].ETXNTTYPE == 1)
{
res.render('error');
}
else
{
db.query('SELECT FIRST 1 ATTENDETXNTID FROM TXATTENDETXNTS ORDER BY ATTENDETXNTID DESC', function(err, rows) {
lastID = 0;
if(rows.length === 1)
{
lastID = rows[0].ATTENDETXNTID;
}
db.query('INSERT INTO TXATTENDETXNTS (ATTENDETXNTID, OPID, DATETIME, ETXNTTYPE, SCANNEDSTR, BRANCHID, CHANGED_FLAG, DEPTID) VALUES (' + (lastID + 1) + ','+ req.params.id +', \''+ moment().format('YYYY-MM-DD HH:mm:ss') +'\', 1, null, 1, 1, 0)', function(err, rows) {
if(err) throw err;
res.render('success');
client.publish('timeclock'+ req.params.id, 'broke out');
});
});
}
});
});
})
})
数据库中的行 table 没有特定的顺序,它们的位置取决于插入的顺序,在数据页上可用 space 免费,插入时哪些页被锁定,和其他因素。此外,查询的结果可能会受到查询计划(包括索引使用)和 I/O 考虑因素的影响。
您的代码 - 特别是 SELECT FIRST 10 * FROM TXATTENDETXNTS ...
查询 - 假定较旧的行在较新的行之前返回。但是,这并不能保证,因此当较新的行出现在较旧的行之前时,您将得到负值。在为计算选择行时,您需要明确指定 ORDER BY
(例如 ORDER BY DATETIME
)。