SQL Server DateDiff - java

I have a SQL Server query that I need to return all dates that are less that 90 days from the current. I thought this was quite trivial until the result set returned was completely wrong. Here's the query.
SELECT new_HwWarrantyEndDate
FROM TABLE
WHERE new_HwWarrantyEndDate IS NOT null
AND DATEDIFF(day,GETDATE(),new_HwWarrantyEndDate) <= 90;
Here are some of the results:
new_HwWarrantyEndDate
---------------------
2010-07-11
2012-12-09
2011-02-12
2012-12-09
2007-12-31
2007-12-31
2007-12-31
2007-12-31
How could this function return dates from years previous?
I have another issue.Why would a query such as:
SELECT DATEDIFF(day,GETDATE(),new_HwWarrantyEndDate) AS DateDiff
FROM TABLE
WHERE Diffdate IS NOT null;
Complain specifically DateDiff is not a valid column when I try and process the resultset ie:
result_set = stmt.executeQuery(query);
Date s;
if(!result_set.next()) {
System.out.println("Null set");
}
while(result_set.next()){
s = result_set.getDate("DateDiff");
System.out.println(s);
}
Thanks I don't have much experience with SQL Server. Any guidance would help.

In SARGable form;
SELECT new_HwWarrantyEndDate
FROM TABLE
WHERE new_HwWarrantyEndDate IS NOT NULL
AND new_HwWarrantyEndDate BETWEEN GETDATE() AND DATEADD(DAY, 90, GETDATE())

Related

Java Sql 'select sum' giving incorrect value

I'm not experienced in java and I'm stuck with this problem and couldn't figure out the cause for weeks. I have a sql query that selects, counts and groups by the column "name". Next in the 'while(rs.next())' I am trying to select the sum of two other columns, a column named "kolicina" and a column named "cena" here is the code of that method:
public ArrayList<Artikli> getSum(String date){
ArrayList<Artikli> list = new ArrayList<Artikli>();
String query = "select name, count(name) as count from izvestaj where dateZat = '"+date+"' group by name";
try {
rs = st.executeQuery(query);
while(rs.next()){
Artikli art = new Artikli();
art.name = rs.getString("name");
String q = "select sum(kolicina) as total from izvestaj where name = '"+art.name+"' and dateZat = '"+date+"'";
rs2 = st2.executeQuery(q);
while(rs2.next()){
art.kolicina = rs2.getInt("total");
}
String q1 = "select sum(cena) as total1 from izvestaj where name = '"+art.name+"' and dateZat = '"+date+"'";
rs3 = st3.executeQuery(q1);
while(rs3.next()){
art.cena = rs3.getInt("total1")/rs.getInt("count");
}
list.add(art);
}
} catch (SQLException e) {
e.printStackTrace();
}
return list;
}
The problem is that the second query returns the correct sum of the column kolicina, but the third query returns result set with the sum multiplied by the count number (from the first query... That's why i divide it with the count in the end), but still, it doesn't actually return the correct ammount. Column "cena" is actually price in english, so it seems that it's making some average price and than multiplies it with the number of records... I double-checked the insert queries and they are fine, so I am sure i insert the correct values. Any help appreciated.
Instead of issuing two distinct queries per name, just issue
select name,
sum(kolicina) as total,
sum(cena) as total1
from izvestaj
where name is not null and
dateZat = ?
group by name
(re. the questino mark : read up on PreparedStatements and how to set up parameterized queries in order to protect yourself properly against SQL injections.)
(I think you can even skip the first query as its results will also be contained in this query's results.)

How can I simplify and reduce execution time of my sql query with specific date format?

I am using jdbcTemplate with following query and code
String sql = select count(*) as count ,trunc(fin.fin_date) as dateAndTime from (select * from rec where rec_status='RECEIVED' and fin_date>sysdate-8) fin group by trunc(fin.fin_date)
try {
return jdbcTemplate.query(sql, new RowMapper<Chrt>() {
#Override
public Chrt mapRow(ResultSet rs, int rowNum) throws SQLException {
Chrt receive = new Chrt();
java.util.Date date =(rs.getDate("dateAndTime"));
receive.setDate(date.toString());
receive.setCount(rs.getInt("count"));
return receive;
}
});
} catch (DataAccessException e) {
return null;
}
}
It returns me date in a format like 2016-05-19 but I need the date like 19-MAY-16. Is it possible to get this format without increasing execution time?
How can I do this?
Instead of the trunc function, you can use the TO_CHAR function. It will give you the date in the specified format:
String sql = select count(*) as count ,TO_CHAR(fin.fin_date, 'DD-MON-YY') as dateAndTime from (select * from rec where rec_status='RECEIVED' and fin_date>sysdate-8) fin group by TO_CHAR(fin.fin_date, 'DD-MON-YY');
This will not impact performances significantly.
To increase performances, I suggest you to look at the query plan for the query. To see this plan, just execute :
EXPLAIN PLAN FOR
select count(*) as count ,TO_CHAR(fin.fin_date, 'DD-MON-YY') as dateAndTime from (select * from rec where rec_status='RECEIVED' and fin_date>sysdate-8) fin group by TO_CHAR(fin.fin_date, 'DD-MON-YY')
in any oracle sql client and read the doc to understand why it is too slow and how to improve performances. (a blind guess : put an index on fin_date)
Why not use one query instead of two ?
select count(*) as count ,TO_CHAR(fin.fin_date, 'DD-MON-YY') as dateAndTime
from rec
where rec_status='RECEIVED' and fin_date>sysdate-8
group by TO_CHAR(fin.fin_date, 'DD-MON-YY');

Datetime is not inserted in table when executing the query through Java

I am using MySQL 5.5 and I am inserting datetime into my table through Java, using the query:
INSERT INTO player_sale(transaction_id,player_id,game_id,game_type_id,ticket_nbr,mrp_amt,deduct_from_bonus,deduct_from_deposit,deduct_from_winning,good_cause_amt,vat_amt,taxable_sale,transaction_date,is_cancel) VALUES(48160,1001501,1,2,0,1.0,0.0,1.0,0.0,0.0,0.0,1.0,'2015-07-09 18:45:01','N');
but the entry inserted is 0000-00-00 00:00:00 in the transaction_date column.
In addition to it, when I am executing the above query, through the query browser interface of MySQL, the correct datetime is inserted . The datatype of transacion_date is datetime.
I have dug out a lot of web, but I couldn't find the answer regarding the same.
I used the following java code :
try{
Timestamp transactionDate = new Timestamp(Calendar.getInstance().getTimeInMillis());
String query="INSERT INTO player_sale(transaction_id,player_id,game_id,game_type_id,ticket_nbr,mrp_amt,deduct_from_bonus,
deduct_from_deposit,deduct_from_winning,good_cause_amt,vat_amt,taxable_sale,transaction_date,is_cancel)
VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?);";
PreparedStatement pt = con.prepareStatement(query);
pt.setLong(1, 1);
pt.setLong(2, 110021);
pt.setInt(3, 1);
pt.setInt(4, 1);
pt.setLong(5, 12345678);
pt.setDouble(6, 10.00);
pt.setDouble(7, 20.00);
pt.setDouble(8,30.00);
pt.setDouble(9, 40.00);
pt.setDouble(10, 10.00);
pt.setDouble(11, 2.00);
pt.setDouble(12, 1.00);
pt.setTimestamp(13, transactionDate);
pt.setString(14, "N");
pstmt.executeUpdate();
}catch(Exception e){
e.printStackTrace();
}

Is it possible to use "WHERE" clause to select all records in SQL Statement?

Good Evening, I am curious if it is possible to make a WHERE-clause in a SQL statement which can show all records?
Below some explanation:
Random SQL Statement (Java)-(JSP example), Normal Situation
String SqlStatement = "SELECT * FROM table_example WHERE First_Col = '<%=passVar%>' ";
db.query(SqlStatement );
//........
//........
What if the passVar is 'ALL', and we need to prompt all the records out when passVar = All? I know I can do it with if-else and check if the passVar is "ALL" then query the without-WHERE statement to make it work..
**without-WHERE statement (Java)-(JSP example)**
if(<%=passVar%> == "ALL") {
SqlStatement = "SELECT * FROM table_example";
} else {
SqlStatement = "SELECT * FROM table_example WHERE First_Col = '<%=passVar%>' ";
}
but can I just code one SQL statement to make all the records prompt? Something like below:
(Java)-(JSP example)
String ShowAll = "";
if(<%=passVar%> == "ALL") {
ShowAll = *;
} else {
ShowAll = <%=passVar%>;
}
SqlStatement = "SELECT * FROM table_example WHERE First_Col = ShowAll ";
Try with WHERE 1=1::
Select * from myTable WHERE 1=1
This also works:
WHERE columnname LIKE '%'
Except for NULL values.
where 1=1 worked for me, Although where clause was being used all records were selected.
You can also try
SELECT * FROM Customers
WHERE CustomerID=CustomerID; /* query */
or
[any_column_name]=[column_name_in_LHL]
(LHL=left hand side.)
copy the query and
click here to try code
It would be better to differ the 2 situations and make 2 queries out of it.
If there is no where condition then the DB does not need to evaluate it (potencially faster)
The source code/debugging output is clearer.
Consider moving the special case inside the query itself, e.g.
SELECT * FROM table_example WHERE '<%=passVar%>' IN ('ALL', First_Col)
Try with wildcard value '%' but I would recommend to use a Factory here to create the SQL statement, what you are trying to do smells a bit.
Something else you could do, is making that combination of code and SQL a single query. Which means the IF..ELSE will be in SQL language.
Check these links for some more info:
MySQL
Using If else in SQL Select statement
On sqlserver you can make proc:
create proc select_all_on_null
#a int
as
begin
select * from Records where (#a is null or Record_id=#a )
end
When you select be your program:
make #a in null will select all
if i is numder there will select row with this id

Execute "sp_msforeachdb" in a Java application

Hi StackOverflow community :)
I come to you to share one of my problems...
I have to extract a list of every table in each database of a SQL Server instance, I found this query :
EXEC sp_msforeachdb 'Use ?; SELECT DB_NAME() AS DB, * FROM sys.tables'
It works perfectly on Microsoft SQL Server Management Studio but when I try to execute it in my Java program (that includes JDBC drivers for SQL Server) it says that it doesn't return any result.
My Java code is the following :
this.statement = this.connect.createStatement(); // Create the statement
this.resultats = this.statement.executeQuery("EXEC sp_msforeachdb 'Use ?; SELECT DB_NAME() AS DB, * FROM sys.tables'"); // Execute the query and store results in a ResultSet
this.sortie.ecrireResultats(this.statement.getResultSet()); // Write the ResultSet to a file
Thanks to anybody who will try to help me,
Have a nice day :)
EDIT 1 :
I'm not sure that the JDBC driver for SQL Server supports my query so I'll try to get to my goal in another way.
What I'm trying to get is a list of all the tables for each database on a SQL Server instance, the output format will be the following :
+-----------+--------+
| Databases | Tables |
+-----------+--------+
So now I'm asking can someone help me to get to that solution using SQL queries thru Java's JDBC for SQL Server driver.
I also wish to thanks the very quick answers I got from Tim Lehner and Mark Rotteveel.
If a statement can return no or multiple results, you should not use executeQuery, but execute() instead, this method returns a boolean indicating the type of the first result:
true: result is a ResultSet
false : result is an update count
If the result is true, then you use getResultSet() to retrieve the ResultSet, otherwise getUpdateCount() to retrieve the update count. If the update count is -1 it means there are no more results. Note that the update count will also be -1 when the current result is a ResultSet. It is also good to know that getResultSet() should return null if there are no more results or if the result is an update count.
Now if you want to retrieve more results, you call getMoreResults() (or its brother accepting an int parameter). The return value of boolean has the same meaning as that of execute(), so false does not mean there are no more results!
There are only no more results if the getMoreResults() returns false and getUpdateCount() returns -1 (as also documented in the Javadoc)
Essentially this means that if you want to correctly process all results you need to do something like below:
boolean result = stmt.execute(...);
while(true)
if (result) {
ResultSet rs = stmt.getResultSet();
// Do something with resultset ...
} else {
int updateCount = stmt.getUpdateCount();
if (updateCount == -1) {
// no more results
break;
}
// Do something with update count ...
}
result = stmt.getMoreResults();
}
NOTE: Part of this answer is based on my answer to Java SQL: Statement.hasResultSet()?
If you're not getting an error, one issue might be that sp_msforeachdb will return a separate result set for each database rather than one set with all records. That being the case, you might try a bit of dynamic SQL to union-up all of your rows:
-- Use sys.tables
declare #sql nvarchar(max)
select #sql = coalesce(#sql + ' union all ', '') + 'select ''' + quotename(name) + ''' as database_name, * from ' + quotename(name) + '.sys.tables'
from sys.databases
select #sql = #sql + ' order by database_name, name'
exec sp_executesql #sql
I still sometimes use INFORMATION_SCHEMA views as well, since it's easier to see the schema name, among other things:
-- Use INFORMATION_SCHEMA.TABLES to easily get schema name
declare #sql nvarchar(max)
select #sql = coalesce(#sql + ' union all ', '') + 'select * from ' + quotename(name) + '.INFORMATION_SCHEMA.TABLES where TABLE_TYPE = ''BASE TABLE'''
from sys.databases
select #sql = #sql + ' order by TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME'
exec sp_executesql #sql
Be aware that this method of string concatenation (select #sql = foo from bar) may not work as you intend through a linked server (it will only grab the last record). Just a small caveat.
UPDATE
I've found the solution !
After reading an article about sp_spaceused being used with Java, I figured out that I was in the same case.
My final code is the following :
this.instances = instances;
for(int i = 0 ; i < this.instances.size() ; i++)
{
try
{
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
this.connect = DriverManager.getConnection("jdbc:sqlserver://" + this.instances.get(i), "tluser", "result");
this.statement = this.connect.prepareCall("{call sp_msforeachdb(?)}");
this.statement.setString(1, "Use ?; SELECT DB_NAME() AS DB, name FROM sys.tables WHERE DB_NAME() NOT IN('master', 'model', 'msdb', 'tempdb')");
this.resultats = this.statement.execute();
while(true)
{
int rowCount = this.statement.getUpdateCount();
if(rowCount > 0)
{
this.statement.getMoreResults();
continue;
}
if(rowCount == 0)
{
this.statement.getMoreResults();
continue;
}
ResultSet rs = this.statement.getResultSet();
if(rs != null)
{
while (rs.next())
{
this.sortie.ecrireResultats(rs); // Write the results to a file
}
rs.close();
this.statement.getMoreResults();
continue;
}
break;
}
this.statement.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
It tried it out and my file has everything I want in it.
Thank you all for your help ! :)

Categories