次の列で構成される MySQL データベースにテーブルがあります。
itemID bigint(11)
itemDate datetime
attributeID smallint(6)
value int(9)
編集:このテーブルには、主キーと関係キーがitemIDである別のテーブルで一意に定義されたアイテムの属性が格納されます。
削除するのに最適な SQL クエリ (?) は何でしょうか(最新のレコードから最も古いレコードまで):
存在する場合、値= 0を持つこのテーブル内の各レコード(同じitemIDと同じattributeIDを持ち、値が5 を超え、itemDateが (古いだけでなく最新の) OR 同一の別のレコード)
このテーブルの各レコードが存在する場合 (同じitemIDと同じattributeIDと同じ値を持ち、itemDateが (古いだけでなく最新の) OR 同一の別のレコード)
最後のコードも参照してください
これをPHPスクリプトで使用しています。
基本的に、約 100,000 のエントリが入力されないほどすぐに特定できなかったバグが原因で、冗長なデータがあります。以下の非常に小さな例:
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;