贝娄是一个示例表。
ID FROM TO DATE
1 Number1 Number2 somedate
2 Number2 Number1 somedate
3 Number2 Number1 somedate
4 Number3 Number1 somedate
5 Number3 Number2 somedate
预期结果是每对唯一的TO和FROM列
获得1行按ID ASC排序的示例结果
(1,Number1,Number2)
(4,Number3,Number1)
(5,Number3,Number2)
好的我已经找到了如何使用以下查询执行此操作
SELECT * FROM table GROUP BY LEAST(to,from), GREATEST(to,from)
但是我无法获得每个唯一对的最新记录。
我尝试使用order by ID desc
,但它会返回唯一对的第一个找到的行。
答案 0 :(得分:4)
SQL小提琴因为某些原因而无法工作,所以在这段时间内你需要帮助我。
假设以下声明有效
SELECT
LEAST(to,from) as LowVal,
GREATEST(to,from) as HighVal,
MAX(date) as MaxDate
FROM table
GROUP BY LEAST(to,from), GREATEST(to,from)
那么你可以加入
select t.*
from
table t
inner join
(SELECT
LEAST(to,from) as LowVal,
GREATEST(to,from) as HighVal,
MAX(date) as MaxDate
FROM table
GROUP BY LEAST(to,from), GREATEST(to,from)
) v
on t.date = v.MaxDate
and (t.From = v.LowVal or t.From = v.HighVal)
and (t.To = v.LowVal or t.To= v.HighVal)
答案 1 :(得分:0)
我相信以下内容可行,我的知识是Microsoft SQL Server,而不是MySQL。如果MySQL缺少其中一个,请告诉我,我将删除答案。
DECLARE @Table1 TABLE(
ID int,
Too varchar(10),
Fromm varchar(10),
Compared int)
INSERT INTO @Table1 values (1, 'John','Mary', 2), (2,'John', 'Mary', 1), (3,'Sue','Charles',1), (4,'Mary','John',3)
SELECT ID, Too, Fromm, Compared
FROM @Table1 as t
INNER JOIN
(
SELECT
CASE WHEN Too < Fromm THEN Too+Fromm
ELSE Fromm+Too
END as orderedValues, MIN(compared) as minComp
FROM @Table1
GROUP BY CASE WHEN Too < Fromm THEN Too+Fromm
ELSE Fromm+Too
END
) ordered ON
ordered.minComp = t.Compared
AND ordered.orderedValues =
CASE
WHEN Too < Fromm
THEN Too+Fromm
ELSE
Fromm+Too
END
我使用的是int而不是time值,但它的工作方式相同。它很脏,但它给了我预期的结果。
它的基础是使用派生查询,您可以在其中获取要获取唯一值的两列,并使用case语句将它们组合成标准格式。在这种情况下,较早的字母顺序与后面的值按字母顺序连接。使用该值来获取我们要查找的最小值,返回到原始表以再次分离出值以及该表中的其他内容。假设我们聚合的值将是唯一的,所以在这种情况下,如果有(1,'John','Mary',2)和(2,'Mary','John',2),它会破坏并返回那对夫妇的2条记录。
答案 2 :(得分:0)
这个答案最初的灵感来自Get records with max value for each group of grouped SQL results 但后来我进一步观察并提出了正确的解决方案。
CREATE TABLE T
(`id` int, `from` varchar(7), `to` varchar(7), `somedate` datetime)
;
INSERT INTO T
(`id`, `from`, `to`, `somedate`)
VALUES
(1, 'Number1', 'Number2', '2015-01-01 00:00:00'),
(2, 'Number2', 'Number1', '2015-01-02 00:00:00'),
(3, 'Number2', 'Number1', '2015-01-03 00:00:00'),
(4, 'Number3', 'Number1', '2015-01-04 00:00:00'),
(5, 'Number3', 'Number2', '2015-01-05 00:00:00');
在MySQL 5.6.19上测试
SELECT *
FROM
(
SELECT *
FROM T
ORDER BY LEAST(`to`,`from`), GREATEST(`to`,`from`), somedate DESC
) X
GROUP BY LEAST(`to`,`from`), GREATEST(`to`,`from`)
结果集
id from to somedate
3 Number2 Number1 2015-01-03
4 Number3 Number1 2015-01-04
5 Number3 Number2 2015-01-05
但是,这依赖于MySQL的一些阴暗行为,将在未来的版本中进行更改。 MySQL 5.7 rejects此查询,因为SELECT子句中的列在功能上不依赖于GROUP BY列。如果它被配置为接受它(ONLY_FULL_GROUP_BY
被禁用),它就像以前的版本一样,但它仍然不是guaranteed:“服务器可以自由选择每个组中的任何值,所以除非它们是相同的,所选择的值是不确定的。“
所以,正确答案似乎是这样的:
SELECT T.*
FROM
T
INNER JOIN
(
SELECT
LEAST(`to`,`from`) AS LowVal,
GREATEST(`to`,`from`) AS HighVal,
MAX(somedate) AS MaxDate
FROM T
GROUP BY LEAST(`to`,`from`), GREATEST(`to`,`from`)
) v
ON T.somedate = v.MaxDate
AND (T.From = v.LowVal OR T.From = v.HighVal)
AND (T.To = v.LowVal OR T.To = v.HighVal)
结果集与上面相同,但在这种情况下保证保持这样,而在您可以轻松获取行Number2, Number1
的不同日期和ID之前,具体取决于您在表上的索引
在原始数据中有两行具有完全相同的somedate
和to
以及from
之前,它将按预期工作。
让我们添加另一行:
INSERT INTO T (`id`, `from`, `to`, `somedate`)
VALUES (6, 'Number1', 'Number2', '2015-01-03 00:00:00');
上面的查询会为2015-01-03
返回两行:
id from to somedate
3 Number2 Number1 2015-01-03
6 Number1 Number2 2015-01-03
4 Number3 Number1 2015-01-04
5 Number3 Number2 2015-01-05
要解决此问题,我们需要一种方法来仅选择组中的一行。在此示例中,我们可以使用唯一ID
来打破平局。如果组中有多个行具有相同的最大日期,我们将选择ID最大的行。
名为Groups
的最内层子查询只返回所有组,例如问题中的原始查询。然后我们向此结果集添加一列id
,我们选择属于同一组的id
,其中somedate
最高,id
最高,ORDER BY
LIMIT
和GroupsWithIDs
。此子查询称为id
。我们拥有所有群组并为每个群组设置了join
正确的行后,我们id
将其添加到原始表中,以便为找到的SELECT T.*
FROM
(
SELECT
Groups.N1
,Groups.N2
,
(
SELECT T.id
FROM T
WHERE
LEAST(`to`,`from`) = Groups.N1 AND
GREATEST(`to`,`from`) = Groups.N2
ORDER BY T.somedate DESC, T.id DESC
LIMIT 1
) AS id
FROM
(
SELECT LEAST(`to`,`from`) AS N1, GREATEST(`to`,`from`) AS N2
FROM T
GROUP BY LEAST(`to`,`from`), GREATEST(`to`,`from`)
) AS Groups
) AS GroupsWithIDs
INNER JOIN T ON T.id = GroupsWithIDs.id
s获取剩余的列。
最终查询
id from to somedate
4 Number3 Number1 2015-01-04
5 Number3 Number2 2015-01-05
6 Number1 Number2 2015-01-03
最终结果集
{{1}}