假设我已经创建了一个SQLITE表,其中包含四个TEXT值first, last, street, state
和两个INTEGER值age, weight
。我想创建一个查询,该查询将选择first, last, street, state
最低的age
的行,如果两个条目的所有weight
的值都相同,则使用first, last, street, state, age
作为决胜分
我想我可以做类似的事情:
SELECT * FROM MyTable
GROUP BY first, last, street, state
ORDER BY age, weight
但是我很确定我刚才给您的查询将从每个first, last, street, state
组中拉出任意行,然后按age, weight
对结果进行排序。我该怎么做才能确定保留GROUP BY的哪一行?我以为我可以代替
SELECT first, last, street, state, MIN(age), MIN(weight) FROM MyTable
GROUP BY first, last, street, state
但是,当然,这将选择最小年龄和最小体重,而不是使用体重作为决胜局的最小年龄。
样品输入:
first, last, street, state, age, weight
John Doe 1 Elm NY 50 120
John Doe 1 Elm NY 35 140
Mark Knopfler 6 Strait CT 67 130
Mary West 32 E St NJ 90 162
Mary West 32 E St NJ 55 120
样品输出:
first, last, street, state, age, weight
John Doe 1 Elm NY 35 140
Mark Knopfler 6 Strait CT 67 130
Mary West 32 E St NJ 55 120
然后我想删除原始表中未选择的条目,但我想那将是一个全新的噩梦。 (基本上,我希望该表就像我在适当的位置上创建一个UNIQUE(第一,最后,街道,州)约束,并通过增大年龄和增大权重来添加行。这将产生等效的结果。)
答案 0 :(得分:0)
我相信以下可能合适:-
-- Select SQL
SELECT rowid, first, street, state, age, weight
FROM mytable AS mt1
WHERE (age * 1000 + weight) = (
SELECT min(age * 1000 + weight)
FROM mytable
WHERE first = mt1.first AND last = mt1.last AND street = mt1.street AND state = mt1.state
ORDER BY (age,weight) ASC
LIMIT 1
)
使用(通过将WITH子句中的查询包装为公用表表达式(CTE),然后使用CTE(cte1)来驱动DELETES来删除SELECT中没有的行,这是一件简单的事情。删除行不在提取的行列表中的行):-
-- Delete SQL
WITH cte1 AS
(
SELECT rowid, first, street, state, age, weight
FROM mytable AS mt1
WHERE (age * 1000 + weight) = (
SELECT min(age * 1000 + weight)
FROM mytable
WHERE first = mt1.first AND last = mt1.last AND street = mt1.street AND state = mt1.state
ORDER BY (age,weight)
LIMIT 1
)
)
DELETE FROM mytable WHERE rowid NOT IN (SELECT cte1.rowid FROM cte1)
;
以上内容通过以下测试:-
-- Load testing data
DROP TABLE IF EXISTS mytable;
CREATE TABLE IF NOT EXISTS mytable (first, last, street, state, age, weight);
INSERT INTO mytable VALUES
('John', 'Doe', '1 Elm', 'NY', 50, 120),
('John', 'Doe', '1 Elm', 'NY', 35, 140),
('John', 'Doe', '1 Elm', 'NY', 35, 139),
('Mark', 'Knopfler', '6 Strait', 'CT', 67, 130),
('Mary', 'West', '32 E St', 'NJ', 90, 88),
('Mary', 'West', '32 E St', 'NJ', 55, 120), -- <<<<<<<<<< duplicated below
('Mary', 'West', '32 E St', 'NJ', 55, 125),
('Mary', 'West', '32 E St', 'NJ', 55, 124),
('Mary', 'West', '32 E St', 'NJ', 55, 120), -- <<<<<<<<<< duplicate
('Mary', 'West', '32 E St', 'NJ', 55, 121)
;
。
-- Show table before deletion
SELECT * FROM mytable;
-- Select SQL (not needed as embedded in delete below)
SELECT rowid, first, street, state, age, weight
FROM mytable AS mt1
WHERE (age * 1000 + weight) = (
SELECT min(age * 1000 + weight)
FROM mytable
WHERE first = mt1.first AND last = mt1.last AND street = mt1.street AND state = mt1.state
ORDER BY (age,weight)
LIMIT 1
)
;
-- Delete SQL
WITH cte1 AS
(
SELECT rowid, first, street, state, age, weight
FROM mytable AS mt1
WHERE (age * 1000 + weight) = (
SELECT min(age * 1000 + weight)
FROM mytable
WHERE first = mt1.first AND last = mt1.last AND street = mt1.street AND state = mt1.state
ORDER BY (age,weight)
LIMIT 1
)
)
DELETE FROM mytable WHERE rowid NOT IN (SELECT cte1.rowid FROM cte1)
;
-- Result after deletion
SELECT * FROM mytable;
以上结果为: