我有一个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-07
和2014-04-08
的值,我需要检索38和47。
我成功使用了两个查询:
SELECT *
FROM values
WHERE date <= $date
ORDER BY date DESC
LIMIT 1
但是,每次都需要dates.length
个请求。所以,我想知道是否有更高效的解决方案可以在一个请求中检索我的所有值?
答案 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 JOIN
为user_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
}
}
}
上排序并选择第一行在此处不起作用,因为您需要返回多个日期的值。