[英]SQL query based on subquery. Retrieve transactions with data > threshold
我的數據庫表稱為事務,如下所示:
Name | Date (DateTime) | Type | Stock | Volume | Price | Total
Tom 2014-05-24 12:00:00 Sell Barclays 100 2.2 220.0
Bob 2014-04-13 15:00:00 Buy Coca-Cola 10 12.0 120.0
varchar DateTime varchar varchar int float float
我最初的問題是從表中刪除屬於用戶的所有事務,該用戶的第一個事務晚於特定閾值。 我的查詢是:
DELETE FROM transactions WHERE name NOT IN (SELECT name FROM transactions2 WHERE date < CAST('2014-01-01 12:00:00.000' as DateTime));
Query OK, 35850 rows affected (3 hours 5 min 28.88 sec)
我認為這是一個糟糕的解決方案,我不得不復制該表以避免從正在讀取的同一表中刪除該表,並且執行花費了相當長的時間(對於包含約170k行的表,該過程花費了3個小時)
現在,我試圖刪除屬於某個用戶的所有交易,該用戶的最新交易發生在某個閾值日期之前。
DELETE FROM transactions WHERE name IN (SELECT name FROM transactions HAVING max(date) < CAST('2015-01-01 12:00:00.000' as DateTime) );
可悲的是,子查詢僅找到一個結果:
SELECT name FROM transactions HAVING max(date) < CAST('2015-01-01 12:00:00.000' as DateTime)';
+------------+
| name |
+------------+
| david |
+------------+
我猜因為max()函數,我只能得到一個結果。 我不是SQL方面的專家,但是我很了解我在集合和邏輯方面的需求。 我真的很樂意就如何重寫查詢提出建議。
編輯:這是與架構和一些數據的sqlfiddle: http ://sqlfiddle.com/#!2/389ede/2
我需要刪除alex的所有條目,因為他的上次交易發生在某個閾值之前(例如,2013年1月1日)。 不需要刪除Tom的交易記錄,因為他的最新交易時間晚於2013年1月1日。
您的第一個查詢可以表述為:`從?中刪除用戶,而在?之前該用戶不存在該交易。 這很容易轉換為sql:
delete from transactions t1
where not exists (
select 1 from transactions t2
where t1.name = t2.name
and t2.date < ?
)
mysql仍然不支持從select引用的表中刪除(AFAIK),因此我們需要將其重寫為:
delete t1.*
from transactions t1
left join transactions t2
on t1.name = t2.name
and t2.date < ?
where t2.name is null
date是保留字,因此您必須引用它。
您的第二個查詢可以用相同的方式解決,在某個日期之后不存在事務的情況下,從事務中刪除。 我將其保留為練習。
艾爾文(Alvin)是從您的提琴和日期中簡化的場景:
CREATE TABLE transactions
( id int(11) NOT NULL AUTO_INCREMENT
, name varchar(30) NOT NULL
, value datetime NOT NULL
, PRIMARY KEY (id) ) ENGINE=InnoDB;
INSERT INTO transactions (name, value) VALUES ('alex', '2011-01-01 12:00:00')
, ('alex', '2012-06-01 12:00:00');
讓我們研究一下發生了什么:
SELECT t1.name as t1_name, t1.value as t1_value
, t2.name as t2_name, t2.values as t2_value
FROM transactions t1
LEFT JOIN transactions t2
ON t1.name = t2.name
T1_NAME T1_VALUE T2_NAME T2_VALUE
alex January, 01 2011 12:00:00+0000 alex January, 01 2011 12:00:00+0000
alex January, 01 2011 12:00:00+0000 alex June, 01 2012 12:00:00+0000
alex June, 01 2012 12:00:00+0000 alex January, 01 2011 12:00:00+0000
alex June, 01 2012 12:00:00+0000 alex June, 01 2012 12:00:00+0000
即4行。 如果現在添加聯接謂詞:
SELECT t1.name as t1_name, t1.value as t1_value
, t2.name as t2_name, t2.values as t2_value
FROM transactions t1
LEFT JOIN transactions t2
ON t1.name = t2.name
AND t2.value > CAST('2011-06-01 12:00.000' as DateTime)
這給我們留下了兩行。 如果將時間更改為'2012-06-01 12:00.000',則由於左連接,我們仍然有兩行,但t2列將為空。
如果現在添加WHERE子句:
SELECT t1.name as t1_name, t1.value as t1_value
, t2.name as t2_name, t2.values as t2_value
FROM transactions t1
LEFT JOIN transactions t2
ON t1.name = t2.name
AND t2.value > CAST('2012-06-01 12:00.000' as DateTime)
WHERE t2.name is null;
我們還有兩排。 使用CAST('2011-06-01 12:00.000'作為DateTime)時,沒有行。
請記住,該構造等效於:
SELECT t1.name as t1_name, t1.value as t1_value
FROM transactions t1
WHERE NOT EXISTS (
SELECT 1 FROM transactions t2
WHERE t1.name = t2.name
AND t2.value > CAST('2012-06-01 12:00.000' as DateTime)
);
因此,如果該名稱不存在value>'2012-06-01 12:00.000'的行,則我們有一個匹配項。 這澄清了嗎?
@ Lennart,Alvin,考慮以下問題...
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table (id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,val INT NOT NULL);
INSERT INTO my_table (val) VALUES (1),(1),(2),(1),(3),(2),(3),(1),(4);
SELECT * FROM my_table;
+----+-----+
| id | val |
+----+-----+
| 1 | 1 |
| 2 | 1 |
| 3 | 2 |
| 4 | 1 |
| 5 | 3 |
| 6 | 2 |
| 7 | 3 |
| 8 | 1 |
| 9 | 4 |
+----+-----+
讓我們刪除每個val
最新結果,即...的結果。
SELECT x.*
FROM my_table x
JOIN
( SELECT val, max(id) max_id FROM my_table GROUP BY val ) y
ON y.val = x.val
AND y.max_id = x.id;
+----+-----+
| id | val |
+----+-----+
| 8 | 1 |
| 6 | 2 |
| 7 | 3 |
| 9 | 4 |
+----+-----+
所以...
DELETE x
FROM my_table x
JOIN ( SELECT val, max(id) max_id FROM my_table GROUP BY val ) y
ON y.val = x.val
AND y.max_id = x.id;
SELECT * FROM my_table;
+----+-----+
| id | val |
+----+-----+
| 1 | 1 |
| 2 | 1 |
| 3 | 2 |
| 4 | 1 |
| 5 | 3 |
+----+-----+
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.