检索几个给定日期之前的几个值

时间:2016-01-20 08:22:27

标签: sql postgresql

我有一个values表,例如:

id | user_id | value | date
---------------------------------
1  |      12 |    38 | 2014-04-05
2  |      15 |    19 | 2014-04-05
3  |      12 |    47 | 2014-04-08

我想检索给定日期的所有值。但是,如果我没有特定日期的值,我想获得之前的可用值。例如,使用上述数据集,如果我查询用户12的日期2014-04-072014-04-08的值,我需要检索38和47。

我成功使用了两个查询:

SELECT *
FROM values
WHERE date <= $date
ORDER BY date DESC
LIMIT 1

但是,每次都需要dates.length个请求。所以,我想知道是否有更高效的解决方案可以在一个请求中检索我的所有值?

1 个答案:

答案 0 :(得分:1)

通常,您可以使用VALUES子句在单个查询中指定多个值。

如果您只偶尔丢失日期(因此任何特定user_id的行之间的日期间隔不大),那么这将是一个优雅的解决方案:

SELECT dt, coalesce(value, lag(value) OVER (ORDER BY dt)) AS value
FROM (VALUES ('2014-04-07'::date), ('2014-04-08')) AS dates(dt)
LEFT JOIN "values" ON "date" = dt AND user_id = 12;

如果当前行没有lag(),则value window function会选择上一个value

另一方面,如果可能存在较大差距,则需要做更多工作:

SELECT DISTINCT dt, first_value(value) OVER (ORDER BY diff) AS value
FROM (
  SELECT dt, value, dt - "date" AS diff
  FROM (VALUES ('2014-04-07'::date), ('2014-04-08')) AS dates(dt)
  CROSS JOIN "values"
  WHERE user_id = 12) sub;

在这种情况下,CROSS JOINuser_id = 12制作VALUES,并在子查询中计算value子句中的日期与计算的表行之间的差异。因此,每一行都有一个字段value的值。在主查询中,使用first_value()窗口函数选择具有最小差异的diff。请注意,在File folder = new File("/Users/you/folder/"); File[] listOfFiles = folder.listFiles(); for (File file : listOfFiles) { if (file.isFile()) { /* * Here if your file is not a text file * If I undersood you correct: * "And how to call that files if it is not stored as String" * you can get it as byte[] and parse it to String */ byte[] bytes = Files.readAllBytes(file.toPath()); String decoded = new String(bytes, "UTF-8"); String[] words = decoded.split("\\s+"); for (int i = 0; i < words.length; i++) { /* You may want to check for a non-word character before blindly * performing a replacement * It may also be necessary to adjust the character class */ words[i] = words[i].replaceAll("[^\\w]", ""); //Here are all the words from a file. You can do whatever you want with them } } } 上排序并选择第一行在此处不起作用,因为您需要返回多个日期的值。