Linq to SQL Server - difficulty with sub-query example - linq-to-sql

I have a SQL Server table that contains the following fields:
SessionId (guid)
Message (varchar)
Timestamp (datetime)
What I need to do is to pull out the FIRST record for EACH SessionId using LINQ to SQL (ideally as a lambda, but query syntax would be useful)
It's relatively simple to do this with t-SQL....
SELECT al.Message, al.SessionId, al.Timestamp
FROM AppLog AS al
WHERE al.Timestamp =
(select MIN(al2.Timestamp) from ApplicationLog as al2 where al2.SessionId = al.SessionId)
I've tried to do the same with a Lambda query (using joins) but it's just not working...
Any/all help will be much appreciated.
Thanks in advance
Griff

I don't know if I'm being simplistic-- but if this is one table, then this should work?
db.Applog.GroupBy(a=>a.SessionID).Select(g=>g.OrderBy(m=>m.Timestamp).First());

You tried using linquer?
http://www.sqltolinq.com/
Query syntax might look a bit nicer than a lambda -
var x = from al in db.AppLog
where al.Timestamp ==
(from al2 in db.ApplicationLog on al2.SessionId equals al.SessionID
select al2.Timestamp).Min())
select new
{
al.Message,
al.SessionId,
al.Timestamp
};

Related

Access query amazing

When I do that on access, SELECT RMonturesImp.N°Fac
FROM RMonturesImp, Rpartielun
WHERE NOT (RMonturesImp.N°Fac IN (1,2,5))
GROUP BY RMonturesImp.N°Fac;
but when I do this
SELECT RMonturesImp.N°Fac
FROM RMonturesImp, Rpartielun
WHERE NOT (RMonturesImp.N°Fac IN Requête2)
GROUP BY RMonturesImp.N°Fac;
it doesn't work (it shows 1,2,5 indeed) although the result of Requête2 (which is a query) is also (1,2,5). I can't understand this!
Thanks in advance
It's quite easy. The IN (1,2,5)) must be explicit as SQL will not evaluate an expression not to say a function to obtain the values for IN.
So build your SQL in code creating the string, or pull the values from a (temp) table.
Try this:
SELECT RMonturesImp.N°Fac
FROM RMonturesImp, Rpartielun
WHERE RMonturesImp.N°Fac NOT IN (Select N°Fac From Requête2)
GROUP BY RMonturesImp.N°Fac;

How best to retrieve result of SELECT COUNT(*) from SQL query in Java/JDBC - Long? BigInteger?

I'm using Hibernate but doing a simple SQLQuery, so I think this boils down to a basic JDBC question. My production app runs on MySQL but my test cases use an in memory HSQLDB. I find that a SELECT COUNT operation returns BigInteger from MySQL but Long from HSQLDB.
MySQL 5.5.22
HSQLDB 2.2.5
The code I've come up with is:
SQLQuery tq = session.createSQLQuery(
"SELECT COUNT(*) AS count FROM calendar_month WHERE date = :date");
tq.setDate("date", eachDate);
Object countobj = tq.list().get(0);
int count = (countobj instanceof BigInteger) ?
((BigInteger)countobj).intValue() : ((Long)countobj).intValue();
This problem of the return type negates answers to other SO questions such as getting count(*) using createSQLQuery in hibernate? where the advice is to use setResultTransformer to map the return value into a bean. The bean must have a type of either BigInteger or Long, and fails if the type is not correct.
I'm reluctant to use a cast operator on the 'COUNT(*) AS count' portion of my SQL for fear of database interoperability. I realise I'm already using createSQLQuery so I'm already stepping outside the bounds of Hibernates attempts at database neutrality, but having had trouble before with the differences between MySQL and HSQLDB in terms of database constraints
Any advice?
I don't known a clear solution for this problem, but I will suggest you to use H2 database for your tests.
H2 database has a feature that you can connect using a compatibility mode to several different databases.
For example to use MySQL mode you connect to the database using this jdbc:h2:~/test;MODE=MySQL URL.
You can downcast to Number and then call the intValue() method. E.g.
SQLQuery tq = session.createSQLQuery("SELECT COUNT(*) AS count FROM calendar_month WHERE date = :date");
tq.setDate("date", eachDate);
Object countobj = tq.list().get(0);
int count = ((Number) countobj).intValue();
Two ideas:
You can get result value as String and then parse it to Long or BigInteger
Do not use COUNT(*) AS count FROM ..., better use something like COUNT(*) AS cnt ... but in your example code you do not use name of result column but it index, so you can use simply COUNT(*) FROM ...

MySQL "in" command

I want to know how we can do this using the IN comparison syntax.
The current SQL query is :
select * from employee
where (employeeName = 'AJAY' and month(empMonth) = month(curdate()))
or (employeeName ='VINAY' and month(empMonth) = month(curdate()))
I tried it using IN comparison function, but am unable to properly set the pieces. Can any one help me?
select * from employee
where employeeName in ('AJAY','VINAY')
and month(empMonth) = month(curdate()); // ERROR.
I tried it in MySQL Query.
Thank You,
Sindhu
Your solution is fine for most DBMS (data-base management systems). As far as I know it is no problem in MySQL. But some years ago I had similar problems in DB2 and also in another more exotic DBMS named "Focus".
Maybe this can help:
Put the complete where-block into a pair of brackets.
Inside this block put each comparison in a pair of brackets again.
Move the IN-Comparison to the end of the where-block.
This would transform your example into this code:
SELECT *
FROM employee
WHERE (
(month(empMonth) = month(curdate())
AND
(employeeName IN ('AJAY','VINAY'))
);

Trying to get the memberid from table

I am trying to get the memberid from database according to text entered in the textbox like this way
String sql =#" SELECT member_Id FROM members where (member_Firstname,'',member_Lastname) ="+tbMemberName.Text;
How can this be done?
Try this:
String sql =#" SELECT member_Id FROM members where CONCAT(member_Firstname,'',member_Lastname) = '"+tbMemberName.Text+"'";
Also, this is vulnerable to sql injection.
Due to security and performance reasons, I would personally split the members's name in first/ last before compiling the query. Now, I'm not familiar with the language you use to call this query, but I'll formulate something that will hopefully make sense, regardless of it's stupidity:
String sql =#" SELECT member_Id FROM members WHERE member_Lastname = "+safely_escaped(tbMembername.Last.Text)+" AND member_Firstname = "+safely_escaped(tbMembername.First.Text)+"
This will allow for a more precise analysis of the names before inserting it into the query and it will allow you to use an index (which is not possible with any of the previously shown examples). Just to be clear, the index, most efficiently in this case, would be INDEX (member_Lastname, member_Firstname).
If that's C# that you're writing, as you've commented, you'll want to start using parameters to avoid SQL injection.
string getMember= #"SELECT member_Id FROM members
WHERE member_Firstname like #userText
OR member_Lastname like #userText;";
MySqlCommand m = new MySqlCommand(getMember);
m.Parameters.AddWithValue("#userText", tbMemberName.Text + "%");
var reader = m.ExecuteReader();

LINQ to SQL - Struggling with query

I have a table with server names and logins. I need to retrieve the logins that are common across a group of servers.
Given the following data:
ServerName Login
-------------------------------
Server1 User1
Server2 User1
Server2 User2
I would pass in Server1,Server2 and get back only User1 as User2 is not associated Server1.
Can anyone tell me how this would be achieved in LINQ to SQL?
I have tried Contains but that returns me all users on any of the servers which is kind of the opposite to what I'm looking for.
EDIT: One of my colleagues managed to write the SQL version of what I'm after....
SELECT Login
FROM ServerLogins
WHERE ServerName IN ('Server1', 'Server2')
GROUP BY Login
HAVING count(Login) = 2
but neither of us know how to translate this into a LINQ query.
ADDITIONAL EDIT:
With Ryan's help and some Googling of the differences in LINQ between VB and C# I got the following to work.
Dim logins = From l In dc.ServerLogins _
Where servers.Contains(l.ServerName) _
Group l By l.Login Into Group _
Where Group.Count() = servers.Count _
Select Login
Thanks again to everyone for their help.
Nick
Here is what I came up with. You'll probably want to check and find out what SQL it actually generates if you're worried about it.
List<string> servers = new List<string>{"Server1", "Server2"};
var logins = from l in context.ServerLogins
where servers.Contains(l.ServerName)
group l by l.Login into g
where g.Count() == servers.Count
select g.Key;
Personally I think this is a good place NOT to use Linq to SQL and instead to use either a sproc or a standard SQL query. I think that even if you were to come up with the correct query in Linq, it would not be very readable and/or efficient.
The SQL you would have would look something like this:
SELECT Login
FROM ServerLogins
WHERE ServerName IN ('Server1', 'Server2')
GROUP BY Login
HAVING COUNT(*) = 2
Note that the "2" in the last line should be replaced with the number of server names in the list above ("IN ('Server1', 'Server2')").
As long as there's a reasonable practical limit on the # of servers being passed in I'd go with something like this:
public ICollection<Login> GetLoginsForServers(params string[] servers)
{
if (servers == null || servers.Length == 0)
return new List<Login>();
var logins = db.Logins.Where(p => p.ServerName == servers[0]);
for (int i=1; i<servers.Length; i++)
{
logins = logins.Intersect(db.Logins.Where(p => p.ServerName == servers[i]));
}
return logins.ToList();
}
Basically you're starting with all the logins associated with the first server then limiting it by those associated with each subsequent. Since the query doesn't get executed until ToList() you still only query the database once, and although the query itself is bound to be ugly, the hope is that the LINQ2SQL provider generates something that will result in an efficient query plan.