Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/77.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 列表中按两列排序的前一项_Mysql_Sql - Fatal编程技术网

Mysql 列表中按两列排序的前一项

Mysql 列表中按两列排序的前一项,mysql,sql,Mysql,Sql,假设我们有一个包含DAY和NUMERO列的表 可以有许多行具有相同的DAY值,但NUMERO始终是唯一的 在一个按天排序的列表中,最有效的方法是什么,在一个现有的两天之前获取项目 我精确地说,我需要mysql使用这个函数,我不想添加一个特定的索引,这就是为什么我不简单地使用DAY和NUMERO的线性函数的原因 下面是一个有序的测试用例: DAY | NUMERO 1 | 11 1 | 12 1 | 15 4 | 7 4 | 9 4 | 14 5 | 8 6 | 1

假设我们有一个包含DAY和NUMERO列的表

可以有许多行具有相同的DAY值,但NUMERO始终是唯一的

在一个按天排序的列表中,最有效的方法是什么,在一个现有的两天之前获取项目

我精确地说,我需要mysql使用这个函数,我不想添加一个特定的索引,这就是为什么我不简单地使用DAY和NUMERO的线性函数的原因

下面是一个有序的测试用例:

DAY | NUMERO
1   | 11
1   | 12
1   | 15
4   | 7
4   | 9
4   | 14
5   | 8
6   | 10
6   | 19
我的请求必须这样做:

1,11=>无

1,15=>1,12

4,7=>1,15

4,9=>4,7

4,14=>4,9

编辑:

我目前的最佳解决方案是进行两次连续查询:

select * from item where day=? and numero<? order by day desc, numero desc limit 1;

select * from item where day<? order by day desc, numero desc limit 1;
如果第一个查询给出结果,我不必运行第二个查询

类似的解决方案是使用一个联合,但mysql似乎并不授权具有多个列的联合

这两种解决方案对于看起来如此简单的问题来说都显得过于沉重…

更新

这是一个实际给出正确结果的解决方案

 SELECT T1.day, 
       T1.numero, 
       COALESCE(MAX(T2.[day]), MAX(T3.[day])) AS prev_day,
       COALESCE(MAX(T2.numero), MAX(T3.numero)) AS prev_numero
FROM @table AS T1
LEFT JOIN @table AS T2 ON 
(
    T2.[day] = T1.[day] AND T2.numero < T1.numero
)
LEFT JOIN @table AS T3 ON  
(
    T3.[day] < T1.[day] 
    AND NOT EXISTS(
        SELECT * 
        FROM @table AS T4
        WHERE T4.[day] > T3.[day] AND T4.[day] < T1.[day]
    )
)
-- Add where clause like so to get specific values
-- WHERE T1.day = 4 AND T1.numero = 7
GROUP BY T1.day, T1.numero
ORDER BY T1.day, T1.numero
更新

这是一个实际给出正确结果的解决方案

 SELECT T1.day, 
       T1.numero, 
       COALESCE(MAX(T2.[day]), MAX(T3.[day])) AS prev_day,
       COALESCE(MAX(T2.numero), MAX(T3.numero)) AS prev_numero
FROM @table AS T1
LEFT JOIN @table AS T2 ON 
(
    T2.[day] = T1.[day] AND T2.numero < T1.numero
)
LEFT JOIN @table AS T3 ON  
(
    T3.[day] < T1.[day] 
    AND NOT EXISTS(
        SELECT * 
        FROM @table AS T4
        WHERE T4.[day] > T3.[day] AND T4.[day] < T1.[day]
    )
)
-- Add where clause like so to get specific values
-- WHERE T1.day = 4 AND T1.numero = 7
GROUP BY T1.day, T1.numero
ORDER BY T1.day, T1.numero

这是一个普通的查询,避免了CTE、聚合或窗口函数

-- (a Before b) := (a.day < b.day
--               OR (a.day = b.day AND a.numero < b.numero))
SELECT d1.day AS DAY
        , d1.numero AS numero
        , d0.day AS day0
        , d0.numero AS numero0
  FROM tmp.lutser d1
  LEFT JOIN tmp.lutser d0
        ON (d0.day < d1.day OR (d0.day = d1.day AND d0.numero < d1.numero ))
  WHERE NOT EXISTS (SELECT *
     FROM tmp.lutser d
     WHERE (dx.day < d1.day OR (dx.day = d1.day AND dx.numero < d1.numero ))
       AND (dx.day > d0.day OR (dx.day = d0.day AND dx.numero > d0.numero ))
     )
ORDER BY day,numero
        ;
结果:

 day | numero | day0 | numero0 
-----+--------+------+---------
   1 |     11 |      |        
   1 |     12 |    1 |      11
   1 |     15 |    1 |      12
   4 |      7 |    1 |      15
   4 |      9 |    4 |       7
   4 |     11 |    4 |       9
   5 |      8 |    4 |      11
   6 |     10 |    5 |       8
   6 |     19 |    6 |      10
(9 rows)

这是一个普通的查询,避免了CTE、聚合或窗口函数

-- (a Before b) := (a.day < b.day
--               OR (a.day = b.day AND a.numero < b.numero))
SELECT d1.day AS DAY
        , d1.numero AS numero
        , d0.day AS day0
        , d0.numero AS numero0
  FROM tmp.lutser d1
  LEFT JOIN tmp.lutser d0
        ON (d0.day < d1.day OR (d0.day = d1.day AND d0.numero < d1.numero ))
  WHERE NOT EXISTS (SELECT *
     FROM tmp.lutser d
     WHERE (dx.day < d1.day OR (dx.day = d1.day AND dx.numero < d1.numero ))
       AND (dx.day > d0.day OR (dx.day = d0.day AND dx.numero > d0.numero ))
     )
ORDER BY day,numero
        ;
结果:

 day | numero | day0 | numero0 
-----+--------+------+---------
   1 |     11 |      |        
   1 |     12 |    1 |      11
   1 |     15 |    1 |      12
   4 |      7 |    1 |      15
   4 |      9 |    4 |       7
   4 |     11 |    4 |       9
   5 |      8 |    4 |      11
   6 |     10 |    5 |       8
   6 |     19 |    6 |      10
(9 rows)

如果您只是基于单个对检索前一对,而不是像其他人提到的那样尝试执行整个表,那么您可以尝试以下简单查询-

:day = 4
:numero = 9

SELECT day, numero
FROM table
WHERE (day = :day AND numero < :numero)
OR (day < :day)
ORDER BY day DESC, numero DESC
LIMIT 1

如果您只是基于单个对检索前一对,而不是像其他人提到的那样尝试执行整个表,那么您可以尝试以下简单查询-

:day = 4
:numero = 9

SELECT day, numero
FROM table
WHERE (day = :day AND numero < :numero)
OR (day < :day)
ORDER BY day DESC, numero DESC
LIMIT 1


好吧,你可以选择当天的maxnumbero,但是numberd比原来的要小。这不会给我4,7中的1,15。有一刻我在思考,我没有看到一个独特的琐碎的问题。我明白了。mysql没有窗口函数?我不这么认为,但我不是mysql或任何DBMS方面的专家,因此我可能缺少一个简单的解决方案。没有窗口函数行数秩或滞后或CTE,就没有简单的解决方案。嗯,你必须构造一组令人讨厌的AND/OR子句。好吧,你可以选择同一天的maxnumbero,但是numberd要比原来的小。这不会给我4,7中的1,15。有一刻我在思考,我没有看到一个独特的琐碎的问题。我明白了。mysql没有窗口函数?我不这么认为,但我不是mysql或任何DBMS方面的专家,因此我可能缺少一个简单的解决方案。没有窗口函数行数秩或滞后或CTE,就没有简单的解决方案。嗯,你必须构造一组讨厌的AND/OR子句。错了。一开始我也是这么想的。参见第二条评论:这不会给我4,7中的1,15,这似乎很有趣,我给你投票,因为我以前不知道coalesce关键字,但我不明白你是如何使用它的。请原谅,如果我是稠密的。获取4,7之前的行的确切请求是什么?@dystroy-docs:@dystroy-要使用它获取特定值,只需添加一个where子句。我更新了我的答案来说明这一点:-其中T1.day=4和T1.numero=7这确实是一个有趣的答案,但我不敢说这是最好的答案,因为即使在第二次尝试时,使用相同的参数,也要慢很多,在一张不到100000行的桌子上,我需要15分钟以上的时间…错了。一开始我也是这么想的。参见第二条评论:这不会给我4,7中的1,15,这似乎很有趣,我给你投票,因为我以前不知道coalesce关键字,但我不明白你是如何使用它的。请原谅,如果我是稠密的。获取4,7之前的行的确切请求是什么?@dystroy-docs:@dystroy-要使用它获取特定值,只需添加一个where子句。我更新了我的答案来说明这一点:-其中T1.day=4和T1.numero=7这确实是一个有趣的答案,但我不敢说这是最好的答案,因为即使在第二次尝试时,使用相同的参数,也要慢很多,因为在一张不到100000行的桌子上,我要花15分钟以上的时间…+1-她很漂亮,我要补充的是,在SQL Server中,至少这一个是一个性能更好的执行工厂。不存在自连接是我最讨厌的事情之一。生成良好的计划,并将在我所知的每个平台上工作,可能是因为习惯用法非常古老/过时。感谢您的见解,但问题与jcooper的答案相同:这是一种缓慢实用的方法。例如,在一个真实数据库上大约100000行的时间是几分钟,而我的dumb two queries解决方案需要几毫秒。dumb two queries只检索1个元组的2个值。库珀和我的检索所有元组。但是你可以在where子句中添加一个限制,当然,正如前面提到的,我想要一个tuple。即使我添加了where子句,它也非常慢。+1-她很漂亮,我至少会在SQL Server中添加它
这是一个性能更好的执行工厂。自我连接不存在是我最讨厌的事情之一。生成良好的计划,并将在我所知的每个平台上工作,可能是因为习惯用法非常古老/过时。感谢您的见解,但问题与jcooper的答案相同:这是一种缓慢实用的方法。例如,在一个真实数据库上大约100000行的时间是几分钟,而我的dumb two queries解决方案需要几毫秒。dumb two queries只检索1个元组的2个值。库珀和我的检索所有元组。但是你可以在where子句中添加一个限制,当然,正如前面提到的,我想要一个tuple。即使我添加了where子句,速度也非常慢。我知道必须有一个简单的解决方案。你知道的。。。我现在觉得自己很笨。。。你赢了。当一个人过度思考问题时,很容易忽视显而易见的东西-我知道必须有一个简单的解决办法。你知道的。。。我现在觉得自己很笨。。。你赢了。当一个人过度思考问题时,很容易忽视显而易见的东西-