简体   繁体   English

选择7天之前JDBC

[英]Select 7 days ago JDBC

Im creating a JDBC to a restaurant database program where an user may see the report of the last 7 days profit. 我在餐厅数据库程序中创建了JDBC,用户可以在其中查看最近7天的利润报告。

I dont know how to select the last seven days, so the program shows the total profit from seven days ago. 我不知道如何选择最近7天,因此程序显示了7天前的总利润。

I would like to know how i can achieve this, my code would look something like this: 我想知道如何实现此目标,我的代码如下所示:

   public static void showSevenDaysAgoSells() {
            double value = 0.0;
            try {       
                System.out.println("----Showing last seven days profit----");
                PreparedStatement stmt = conn.prepareStatement("SELECT sum(total) FROM sells WHERE date > date_from_7_days_ago");
                java.sql.Date date= new java.sql.Date(new java.util.Date().getTime());
                stmt.setObject(1, LocalDate.now(ZoneId.of("America/Caracas")).minusWeeks(1));               
                stmt.executeQuery();
                ResultSet rs = stmt.executeQuery();
                rs.next();
                String sum = rs.getString(1);
                value = Double.parseDouble(sum);
                System.out.println("DAYS" + "\t" +  "TOTAL");
                System.out.println(date+ "\t" + sum);
                } catch(Exception e) {
                e.printStackTrace();
            }
        }

tl;dr TL;博士

PreparedStatement stmt = conn.prepareStatement(
    "SELECT sum( total_ ) FROM sells_ WHERE date_ > ? ;"
);

…and… …和…

stmt.setObject(                            // Use JDBC 4.2 method for passing/fetching java.time types.
    1 ,                                    // Specify which placeholder `?` in PreparedStatement (1, 2, 3, etc.). In this case, `1`. 
    LocalDate.now(                         // Get current date (today) in desired/expected time zone. 
        ZoneId.of( "America/Montreal" )
    ).minusWeeks( 1 )                      // Go back in time a week (7 days).
)

?

You embedded your variable date_from_7_days_ago within your SQL string. 您将变量date_from_7_days_ago嵌入到SQL字符串中。 So it is treated as a string literal rather than as a Java variable's passed value. 因此,它被视为字符串文字,而不是Java变量的传递值。 Replace that variable name with the question mark ? 用问号替换该变量名? placeholder for the PreparedStatement . PreparedStatement占位符。

PreparedStatement stmt = conn.prepareStatement( "SELECT sum( total_ ) FROM sells_ WHERE date_ > ? ;" );

Tip: Avoid naming your columns and other database identifiers with a reserved words such as date and total . 提示:避免使用保留字(例如datetotal命名列和其他数据库标识符。 Various SQL databases in total reserve over a thousand reserved words, so a collision is easier than people realize. 各种SQL数据库总共保留一千多个保留字,因此发生冲突比人们意识到的容易。 The SQL spec explicitly promises to never reserve any word with a trailing underscore. SQL规范明确承诺绝不保留带下划线的任何单词。 So name all your identifiers date_ , total_ , and such to never worry about collisions. 因此,将所有标识符date_total_ ,这样就total_担心冲突了。

Avoid legacy date-time classes 避免使用旧的日期时间类

Both the Question and the other Answer use the troublesome old date-time classes that have proven to be poorly designed, confusing, and flawed. 问题和其他答案都使用麻烦的旧日期时间类,事实证明它们设计不良,混乱且有缺陷。 They are now legacy, supplanted by the java.time classes. 它们现在已被遗留,由java.time类取代。

The java.time.LocalDate class represents a date-only value without time-of-day and without time zone. java.time.LocalDate类表示没有日期和时区的仅日期值。

Time Zone 时区

Both the Question and other Answer ignore the crucial issue of time zone. 问题和其他答案都忽略了时区这一关键问题。

A time zone is necessary in determining a date. 确定日期时需要时区。 For any given moment, the date varies around the globe by zone. 在任何给定时刻,日期都会在全球范围内变化。 For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec . 例如, 法国巴黎午夜过后几分钟是新的一天,而在魁北克蒙特利尔仍然是“昨天”。

Specify a proper time zone name in the format of continent/region , such as America/Montreal , Africa/Casablanca , or Pacific/Auckland . continent/region的格式指定正确的时区名称 ,例如America/MontrealAfrica/CasablancaPacific/Auckland Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!). 切勿使用ESTIST等3-4个字母的缩写,因为它们不是真实的时区,不是标准化的,甚至不是唯一的(!)。

ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( z );

If your business logic requirements dictate UTC rather than a particular time zone, use the constant ZoneOffset.UTC . 如果您的业务逻辑要求规定了UTC而不是特定的时区,请使用常量ZoneOffset.UTC

LocalDate today = LocalDate.now( ZoneOffset.UTC ) ;

To get seven days ago (a week), let the object do the date-math. 要获得7天(一周)的时间,请让该对象执行date-math。

LocalDate weekAgo = LocalDate.minusWeeks( 1 );

JDBC JDBC

If your JDBC driver complies with JDBC 4.2 and later, you can directly use the java.time types via PreparedStatement.setObject and ResultSet.getObject . 如果您的JDBC驱动程序符合JDBC 4.2及更高版本,则可以通过PreparedStatement.setObjectResultSet.getObject直接使用java.time类型。

myPreparedStatement.setObject( … , weekAgo );

and retrieve: 并检索:

LocalDate ld = myResultSet.getObject( … , LocalDate.class );

At least these two JDBC drivers for Postgres may have been updated for JDBC 4.2 though I have not yet tested them for support of java.time types. 至少针对Postgres的这两个JDBC驱动程序可能已针对JDBC 4.2更新,尽管我尚未测试它们是否支持java.time类型。

If your JDBC driver does not comply, then fall back to using java.sql. 如果您的JDBC驱动程序不符合要求,则退回到使用java.sql。 But do so as briefly as possible, converting to/from java.time immediately. 但是,请尽可能简短地进行操作,立即将其转换为java.time。 To convert, look to new methods added to the old classes. 要进行转换,请查看添加到旧类中的新方法。 In this case we would have to fall back to using java.sql.Date using the valueOf and toLocalDate methods. 在这种情况下,我们将不得不使用valueOftoLocalDate方法来使用java.sql.Date

myPreparedStatement.setObject( … , java.sql.Date.valueOf( weekAgo ) );

and retrieve: 并检索:

LocalDate ld = myResultSet.getDate( … ).toLocalDate() ;

About java.time 关于java.time

The java.time framework is built into Java 8 and later. java.time框架内置于Java 8及更高版本中。 These classes supplant the troublesome old legacy date-time classes such as java.util.Date , Calendar , & SimpleDateFormat . 这些类取代了麻烦的旧的旧式日期时间类,例如java.util.DateCalendarSimpleDateFormat

The Joda-Time project, now in maintenance mode , advises migration to the java.time classes. 现在处于维护模式Joda-Time项目建议迁移到java.time类。

To learn more, see the Oracle Tutorial . 要了解更多信息,请参见Oracle教程 And search Stack Overflow for many examples and explanations. 并在Stack Overflow中搜索许多示例和说明。 Specification is JSR 310 . 规格为JSR 310

Where to obtain the java.time classes? 在哪里获取java.time类?

The ThreeTen-Extra project extends java.time with additional classes. ThreeTen-Extra项目使用其他类扩展了java.time。 This project is a proving ground for possible future additions to java.time. 该项目为将来可能在java.time中添加内容提供了一个试验场。 You may find some useful classes here such as Interval , YearWeek , YearQuarter , and more . 您可以在这里找到一些有用的类,比如IntervalYearWeekYearQuarter ,和更多

Do

    final long OneDayMillis = 86400000l;
    PreparedStatement stmt = conn.prepareStatement("SELECT sum(total) FROM sells WHERE date > ?");
    java.sql.Date date = new java.sql.Date(System.currentTimeMillis()-OneDayMillis*7l);
    stmt.setDate(1, date);

Take into account that the current date of your server might be different from the current date of your client machine, therefore it may be better to use server-side date with a SQL statement like 考虑到服务器的当前日期可能与客户端计算机的当前日期不同,因此最好将服务器端日期与SQL语句一起使用,例如

SELECT sum(total) FROM sells WHERE date > current_date - integer '7'

without any parameter binding from client side. 没有客户端的任何参数绑定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM