我在 MySQL 数据库中有一个表,其中包含以下列:
itemID bigint(11)
itemDate datetime
attributeID smallint(6)
value int(9)
编辑:此表存储在一个单独的表中唯一定义的项目的属性,其主键和关系键是itemID。
最好删除的 SQL 查询 (?) 是什么(从最近的记录开始到最旧的记录):
此表中值= 0(如果存在)的每条记录(具有相同itemID和相同属性ID且值>5 且itemDate为(较旧但也是最新)或相同的另一条记录)
此表中的每条记录(如果存在)(具有相同itemID和相同attributeID和相同值的另一条记录,并且itemDate是(较旧但也是最近的)或相同)
也见最后的代码
我在 PHP 脚本中使用它。
基本上,我有多余的数据,因为我没有尽快发现它没有填充大约 100k 条目的错误。下面是一个非常小的例子:
itemID itemDate attributeID value
28 11.09.2013 2:00 4 0
28 11.09.2013 2:00 5 0
28 11.09.2013 2:01 1 0
28 11.09.2013 2:01 2 0
28 11.09.2013 2:01 3 0
28 11.09.2013 2:01 4 0
28 11.09.2013 2:01 5 0
28 11.09.2013 2:02 1 21
28 11.09.2013 2:02 2 11
28 11.09.2013 2:02 3 4
28 11.09.2013 2:02 1 21
28 11.09.2013 2:02 2 11
28 11.09.2013 2:02 3 4
28 11.09.2013 2:02 1 21
28 11.09.2013 2:02 2 12
28 11.09.2013 2:02 3 4
28 13.09.2013 18:54 1 0
28 13.09.2013 18:54 2 0
28 13.09.2013 18:54 3 0
28 13.09.2013 18:55 1 21
28 13.09.2013 18:55 2 12
28 13.09.2013 18:55 3 6
上面应该变成(删除算法的多次迭代后):
itemID itemDate attributeID value
28 11.09.2013 2:00 4 0
28 11.09.2013 2:00 5 0
28 11.09.2013 2:01 1 0
28 11.09.2013 2:01 2 0
28 11.09.2013 2:01 3 0
28 11.09.2013 2:02 1 21
28 11.09.2013 2:02 2 11
28 11.09.2013 2:02 3 4
28 11.09.2013 2:02 2 12
28 13.09.2013 18:55 3 6
我希望我足够清楚地定义了问题,但是,如果我应该澄清任何事情,请告诉我。非常感谢你!
更新
我设法找到了一个结合 SQL 和 php 的解决方案,但我不太喜欢它。我确实相信通过 2 个正确的 SQL 查询可以获得相同的结果,因此,尽管我很满意我有办法清理我的数据库,但问题仍然存在:如何将下面的代码转换为纯 sql 查询。
// Properties
$item_found_count = $item_valid_count = 0;
// Find zero value entries
$query = "SELECT * FROM $db_fb WHERE value = '0'";
if ($result = mysqli_query($connection, $query)) {
// for each record found
while($row = $result->fetch_array()) {
$item_found_count++; // Count all items found
$t_itemID = $row['itemID']; $t_itemDate = $row['itemDate']; $t_attributeID = $row['attributeID']; // Record this data just in case we need it as a 'pointer' to delete the record
//echo "Entry found: " . $row['itemID'] . " " . $row['itemDate'];
$query = "SELECT * FROM $db_fb WHERE itemID = $t_itemID AND itemDate < '$t_itemDate' AND attributeID = '$t_attributeID' AND value > '5' ORDER BY itemDate DESC LIMIT 1";
// If there is such an entry, the current one must be deleted.
if ($SecondResult = mysqli_query($connection, $query)) {
while($rowSpec = $SecondResult->fetch_array()) {
$item_valid_count++; // Count all items actually deleted
//echo "<br>-> mark;"; print_r($rowSpec); echo "<br>";
// Delete if ID, itemDate, attributeID and VALUE coincide
$q_del = "DELETE FROM $db_fb WHERE itemID = $t_itemID AND itemDate = '$t_itemDate' AND attributeID = '$t_attributeID' AND value = '0'";
$deleteRes = mysqli_query($connection, $q_del);
}
}
//echo "--------------------------<br><br>";
}
}
// Select from table where values are identical, attributeID identical, ID identical, itemDates immediately consecutive LIMIT by 2. Delete most recent entry.
$query = "SELECT MAX(itemDate) as itemDate, itemID, attributeID, value, count(*) FROM $db_fb GROUP BY itemID, attributeID, value HAVING count(*) > 1 ORDER BY itemDate DESC";
if ($ThirdResult = mysqli_query($connection, $query)) {
while($rowSpec = $ThirdResult->fetch_array()) {
$item_duplicates_count++; // Count all items actually deleted
$t_itemID = $rowSpec['itemID']; $t_itemDate = $rowSpec['itemDate']; $t_attributeID = $rowSpec['attributeID']; $t_value = $rowSpec['value']; // Record this data just in case we need it as a 'pointer' to delete the record
//echo "<br>-> mark;"; print_r($rowSpec); echo "<br>";
$q_del = "DELETE FROM $db_fb WHERE itemID = '$t_itemID' AND itemDate = '$t_itemDate' AND attributeID = '$t_attributeID' AND value = '$t_value'";
$deleteRes = mysqli_query($connection, $q_del);
}
}
echo "Zeroed found: " . $item_found_count . "<br>";
echo "Zeroed valid for deletion: " . $item_valid_count . "<br>";
echo "Zeroed remaining: " . ($item_found_count - $item_valid_count) . "<br>";
echo "Consecutive duplicates: " . $item_duplicates_count;