How can I do the following sql code with linq?
SQL;
SELECT BusinessEntityID, FirstName + ' ' + LastName AS "FullName"
FROM Person WHERE FullName LIKE 'a%'
LINQ;
using(var db= new db_Context)
{
var query = db.Person.Select(q=> q.FirstName + " "+ q=>q.FullName)
}
Searching after concatenate the strings is not a good idea. I recommend the search for firstname and lastname separately
var query = db.Person.Where (t => t.FirstName.StartsWith("a") || t.LastName.StartsWith("a") )
.Select(q=> new { q.BusinessEntityID, Fullname = q.FirstName + " " + q.LastName })
Following code will be helpful to you,
var list1 = db.Person.Where (t => t.FirstName.StartsWith("a"))
.Select(q=> new {
BusinessEntityID = q.BusinessEntityID,
Fullname = q.FirstName + " " + q.LastName
});
Or
var list2 = from psn in db.Person
where psn.FirstName.StartsWith("a")
select new {
BusinessEntityID = psn.BusinessEntityID,
Fullname = psn.FirstName + " " + psn.LastName
};
Related
I have a prepared statement in my application and it takes 3 minutes to give an results. However, same query i have executed in sql developer and it only takes less than 0.1 seconds to give the results. I have done research on this throughout last week and I couldn't find a proper solution. Here is my code.
public List<ResponseDto> loadData(RequestDto request) throws SQLException {
List<ResponseDto> responseDto = new ArrayList<>();
int sortBy = request.getSortBy();
String sql = "SELECT *" +
"FROM (SELECT r.*, ROWNUM RNUM, COUNT(*) OVER () RESULT_COUNT " +
" FROM (SELECT *" +
"FROM" +
" (SELECT r.VALUE_4," +
" r.DATE," +
" r.ID," +
" r.AMOUNT," +
" r.TO_AGENT_ID," +
" r.FROM_AGENT_ID," +
" a.NAME," +
" r.VALUE_2," +
" r.VALUE_1," +
" r.STATUS," +
" r.VALUE_3," +
" r.TEXT" +
" FROM MY_TABLE r" +
" INNER JOIN AGENT a " +
" ON a.AGENT_ID=r.TO_AGENT_ID" +
" WHERE r.STATUS = 1 " +
" AND r.ID IN" +
" (SELECT T.ID FROM TEST_TABLE T" +
" INNER JOIN AGENT af" +
" ON af.AGENT_ID = T.FROM_AGENT_ID " +
" INNER JOIN AGENT at" +
" ON at.AGENT_ID=T.TO_AGENT_ID" +
" WHERE T.FROM_AGENT_ID=?";
StringBuilder sbQuery = new StringBuilder(sql);
if (request.getToAgentId() != 0) {
sbQuery.append(" AND T.TO_AGENT_ID = ? ");
} else if (request.getQueryParam() != null && !request.getQueryParam().equalsIgnoreCase("")) {
sbQuery.append(" AND UPPER(at.NAME) like UPPER( ? ) ");
}
String secondPart =
" AND T.STATUS = 1" +
" AND TO_DATE(T.DATE) BETWEEN TO_DATE(?, 'yyyy-MM-dd') AND TO_DATE(?, 'yyyy-MM-dd')" +
" ) " +
" or r.VALUE_3=?";
sbQuery.append(secondPArt);
if (sortBy == 1) {
sbQuery.append(" ORDER BY a.NAME ");
} else if (sortBy == 2) {
sbQuery.append(" ORDER BY r.AMOUNT ");
} else if (sortBy == 3) {
sbQuery.append(" ORDER BY r.VALUE_4 ");
}
if (request.getSortingOrder() == 1) {
sbQuery.append("DESC ");
} else if (request.getSortingOrder() == 2) {
sbQuery.append("ASC ");
}
sbQuery.append(" )) R)" +
"WHERE RNUM between ? and ?");
String sqlq = sbQuery.toString();
log.info(sqlq);
try(Connection con = dataSource.getConnection(); PreparedStatement pstmt = con.prepareStatement(sbQuery.toString()) ) {
con.setAutoCommit(false);
String nameParam = "%" + request.getQueryParam() + "%";
pstmt.setLong(1, request.getFromAgentId());
if (request.getToAgentId() != 0) {
pstmt.setLong(2, request.getToAgentId());
} else if(request.getQueryParam() != null && !request.getQueryParam().equalsIgnoreCase("")) {
pstmt.setString(2, request.getQueryParam());
}
pstmt.setString(3, request.getFromDate());
pstmt.setString(4, request.getToDte());
pstmt.setString(5, request.getQueryParam());
pstmt.setLong(6, request.getFromIndex());
pstmt.setLong(7, request.getToIndex());
responseDto = helperMethod(pstmt);
con.commit();
} catch (SQLException e) {
log.error(e.getMessage());
throw e;
}
return responseDto;
}
public List<MyDto> helperMethod(PreparedStatement pstmt) throws SQLException {
List<MyDto> myDtoList = new ArrayList<>();
try( ResultSet rs = pstmt.executeQuery()) {
while (rs.next()) {
MyDto myDto = new MyDto();
myDto.setValue4(rs.getLong("VALUE_4"));
myDto.setDate(rs.getDate("DATE"));
myDto.setTransactionId(rs.getLong("ID"));
myDto.setAmount(rs.getLong("AMOUNT"));
myDto.setToAgentId(rs.getLong("TO_AGENT_ID"));
myDto.setFromAgentId(rs.getLong("FROM_AGENT_ID"));
myDto.setName(rs.getString("NAME"));
myDto.setValue2(rs.getLong("VALUE_2"));
myDto.setValue1(rs.getLong("VALUE_1"));
myDto.setStatus(rs.getInt("STATUS"));
myDto.setValue3(rs.getString("VALUE_3"));
myDto.setText(rs.getString("TEXT"));
myDtoList.add(myDto);
}
}catch (Exception ex){
log.error(ex.getMessage());
throw ex;
}
return myDtoList;
}
As I said, same query works with in milliseconds. I really don't know what i am doing wrong here.
Any help would be grateful !
This is not a direct answer, but may hopefully point you in the right direction. First off, depending on your conditionals, there are different variations of what SQL is executed. I would try the following:
Edit the select string and embed a unique comment in it so we can find it in the next step. Example : "select /*mytest*/ * from ..."
Execute your program. Then locate the query in the v$sqlarea such as: select sql_id from v$sqlarea where instr(sql_fulltext,'mytest') > 0;
using the sql_id value from Step #2, execute SELECT * FROM table(DBMS_XPLAN.DISPLAY_CURSOR('sql_id',0));
this will show you the execution plan, and hopefully you will see the difference maybe a full table scan is happening or index not getting used. etc. Do similar steps for the direct sql query that is faster and see what the differences are.
Suppose I query a table which contains raw json in a column, or create json myself with a subquery like this:
select
p.name,
(select json_build_array(json_build_object('num', a.num, 'city', a.city)) from address a where a.id = p.addr) as addr
from person p;
How can I instruct Spring's NamedParameterJdbcTemplate not to escape
the addr column but leave it alone?
So far it insists returning me something like this:
[{
name: "John",
addr: {
type: "json",
value: "{"num" : "123", "city" : "Luxembourg"}"
}
}]
This is the working solution.
Service:
#Transactional(readOnly = true)
public String getRawJson() {
String sql = "select json_agg(row_to_json(json)) from ( "
+ "select "
+ "p.id, "
+ "p.name, "
+ "(select array_to_json(array_agg(row_to_json(c))) from ( "
+ " ... some subselect ... "
+ ") c ) as subq "
+ "from person p "
+ "where type = :type "
+ ") json";
MapSqlParameterSource params = new MapSqlParameterSource("type", 1);
return jdbcTemplate.queryForObject(sql, params, String.class);
}
Controller:
#ResponseBody
#GetMapping(value = "/json", produces = MediaType.APPLICATION_JSON_VALUE)
public String getRawJson() {
return miscService.getRawJson();
}
The key is the combination of json_agg and row_to_json / array_to_json plus returning a String to avoid any type conversions.
I have the following sql statement pulling data from a stored view:
foreach (var id in insert_idlist[0])
{
mssql_con.Open();
//top 1 for duplicate removal
//slowdown?
var mssql_select = "SELECT * FROM dbo.export_to_web WHERE SKU = '" + id + "'";
}
I want to rewrite the sql statement to insert all ids into a single query using an IN clause or similar to speed up execution. However I am aware that IN is a relatively slow operation, so I was hoping to get some expert advice on the fastest possible way of retrieving my data.
Speed is my only concern in this question.
Please note that security is not an issue as this application is pulling all it's variables from an internal database with no direct web access.
Updated code:
try
{
//foreach (var id in insert_idlist[0])
//{
mssql_con.Open();
//top 1 for duplicate removal
//slowdown?
//var mssql_select = "SELECT * FROM dbo.export_to_web WHERE SKU = '" + id + "'";
var mssql_select = "SELECT * FROM dbo.export_to_web WHERE SKU IN (" + insert_idlist .Select(x => "'" + x + "'") .Aggregate((x, y) => x + "," + y) + ")";
//var mssql_select = "SELECT * FROM dbo.Book5 WHERE SKU = '"+id+"'";
SqlCommand cmd = new SqlCommand(mssql_select, mssql_con);
cmd.CommandTimeout = 0;
lbl_dev.Text += "teest";
//Create a data reader and Execute the command
try
{
SqlDataReader dataReader = cmd.ExecuteReader();
//Read the data and store them in the list
while (dataReader.Read())
{
insert_idlist[1].Add(dataReader["supplier name"] + " " + dataReader["range description"] + " " + dataReader["item description"]);
insert_idlist[3].Add(dataReader["Sale Price"] + "");
insert_idlist[2].Add(dataReader["WebDesc"] + "");
//insert_idlist[3].Add(dataReader["id"] + "");removed
insert_idlist[4].Add(dataReader["WebDimensions"] + "");
insert_idlist[5].Add(dataReader["RRP"] + "");
insert_idlist[6].Add(dataReader["Normal Price"] + "");
insert_idlist[7].Add("482"); //add me
insert_idlist[8].Add(dataReader["ID"] + "");
lbl_dev.Text += dataReader["supplier name"] + " " + dataReader["range description"] + " " + dataReader["item description"];
lbl_dev.Text += mssql_select;
about_to_insert = about_to_insert + 1;
}
lbl_dyn_status.Text = "Record 0 of " + about_to_insert + "updated.";
dataReader.Close();
mssql_con.Close();
}
catch (Exception e)
{
lbl_dev.Text = "" + e.Message;
}
// }
}
catch (Exception e)
{
lbl_dev.Text = "" + e.Message;
}
I want to rewrite the sql statement to insert all ids into a single
query using an IN clause or similiar.
You can use INSERT INTO ... SELECT ... like so:
INSERT INTO ATable(...)
SELECT * FROM dbo.export_to_web WHERE SKU = someid;
Note that: You have to list the columns' names in the INSERT clause to match what is returned by SELECT *.
If you are on 2008 or higher, the best way to do is pass the values into a Table-Valued Parameter. I always point people to a blog post I wrote here for that.
However, IN is not necessarily a slow operation, as long as the field that you are searching is indexed appropriately - and it would almost certainly be faster than the 'connection per item' approach.
The SQL would then be something like:
var mssql_select = "SELECT * FROM dbo.export_to_web WHERE SKU IN (" + insert_idlist
.Select(x => "'" + x + "'")
.Aggregate((x, y) => x + "," + y) + ")";
Disclaimer - that LINQ may not be 100% spot on :)
is there any problems with the (var query4) coz th aps desn't show me any msg but it can't insert the data into the table concerne
#{
var userId = Request["UserId"];
var Type = Request["type"];
var db = Database.Open("intranet");
if(Type == "delete")
{
var query = "UPDATE Personne SET Demande = 'refuser' WHERE UserId = '" + userId + "'";
db.Execute(query);
var query2 = "DELETE from DemandeConge where UserId = '" + userId + "'";
db.Execute(query2);
}
else if(Type == "accepte")
{
var query = "UPDATE Personne SET Demande = 'accepte' WHERE UserId = '" + userId + "'";
db.Execute(query);
var query2 = "DELETE from DemandeConge where UserId = '" + userId + "'";
db.Execute(query2);
var query4 = "INSERT INTO CongeAccept(UserId,DateDebut,DateFin,TypeConge) SELECT UserId,DateDebutDemande,DateFinDemande,TypeConge FROM DemandeConge WHERE UserId = '" + userId + "'";
db.Execute(query4);
}
}
and whene i make the comment into this code it works as well :
/* var query = "UPDATE Personne SET Demande = 'accepte' WHERE UserId = '" + userId + "'";
db.Execute(query);
var query2 = "DELETE from DemandeConge where UserId = '" + userId + "'";
db.Execute(query2);*/
var query4 = "INSERT INTO CongeAccept(UserId,DateDebut,DateFin,TypeConge) SELECT UserId,DateDebutDemande,DateFinDemande,TypeConge FROM DemandeConge WHERE UserId = '" + userId + "'";
db.Execute(query4);
}
You are deleting everything from DemandeConge relating to the user you want to insert into CongeAccept so when the try the insert query, there is nothing there to insert. Change the order of your statements and use parameters:
#{
var userId = Request["UserId"];
var Type = Request["type"];
var db = Database.Open("intranet");
if(Type == "delete")
{
var query = "UPDATE Personne SET Demande = 'refuser' WHERE UserId = #0";
db.Execute(query, userId);
var query2 = "DELETE from DemandeConge where UserId = #0";
db.Execute(query2, userId);
}
else if(Type == "accepte")
{
var query = "UPDATE Personne SET Demande = 'accepte' WHERE UserId = #0";
db.Execute(query, userId);
var query4 = "INSERT INTO CongeAccept(UserId,DateDebut,DateFin,TypeConge) SELECT UserId,DateDebutDemande,DateFinDemande,TypeConge FROM DemandeConge WHERE UserId = #0";
db.Execute(query4, userId);
var query2 = "DELETE from DemandeConge where UserId = #0";
db.Execute(query2, userId);
}
}
sql = " SELECT * FROM userDetail ";
sql += " WHERE userId IN ";
sql += " (SELECT friendId FROM userFriends ";
sql += " WHERE approvalStatus='True' AND userId=" + userId;
sql += " UNION";
sql += " SELECT userId FROM userFriends ";
sql += " WHERE approvalStatus='True' AND friendId=" + userId + ")";
In LINQ, you could be something like:
var approvedUsers = db.UserFriends.Where(p => p.ApprovalStatus == "True");
var userIds = from p in approvedUsers
where p.UserId == userId || p.FriendId = userId
select p.UserId;
var friendsAndUser = db.UserDetails
.Where(detail => userIds.Contains(detail.UserId));
Alternatively, use a join:
var query = from user in db.UserFriends
where p.ApprovalStatus == "True"
where p.UserId == userId || p.FriendId == userId
join detail in db.UserDetails on user.UserId equals detail.UserId
select detail;
I suspect neither of these would use a union. You could use a union with LINQ, like this:
var approvedUsers = db.UserFriends.Where(p => p.ApprovalStatus == "True");
var userIds = from p in approvedUsers
where p.UserId == userId
select p.UserId;
var friendIds = from p in approvedUsers
where p.FriendId = userId
select p.UserId;
var allIds = userIds.Union(friendIds);
var friendsAndUser = db.UserDetails
.Where(detail => userIds.Contains(detail.UserId));
... but that's a lot of fuss. I'd probably go with the join.