How do I write a Linq to SQL query with a cast? - linq-to-sql

How do i write a Linq to SQL query that translates into the following:
SELECT CAST(DATETEXT AS datetime) FROM mytable

var dates = from row in mytable
select DateTime.Parse(row.DATETEXT);
There are method overloads for DateTime.Parse that allow you to specify a format.

actually, you won't be needing that. just parse it as datatime when you will use the field value. here is an exaple;
var query = from c in mytable
select c;
then when you will use it;
DateTime _value = (DateTime)query.SingleOrDefault().DATETEXT
but if you wanna use it so much. here is an example;
NorthwindEntities _e = new NorthwindEntities();
public void poo() {
var query = from e in _e.Products
select DateTime.Parse(e.DateText);
}

Related

What's wrong with this SQL query WHERE AND clause?

Previously, this was working:
$patient_story_set_photos = $wpdb->get_results('SELECT * FROM wp_before_after WHERE patientID = '.$post->ID.' AND patient_display = 1');
However, when I try to add another AND condition like this:
$patient_story_set_photos = $wpdb->get_results('SELECT * FROM wp_before_after WHERE patientID = '.$post->ID.' AND patient_display = 1 AND period_taken = '.$set->period_taken);
I get the following error on screen:
WordPress database error: [Unknown column '1hour' in 'where clause']
SELECT * FROM wp_before_after WHERE patientID = 8175 AND patient_display = 1 AND period_taken = 1hour
Can't see why there's a problem, are you not allowed to use multiple AND conditions in SQL?
The problem is not the AND, the problem is your 1hour, 1hour unquoted means a reference to an object (database, table) named 1hour, you need to quote '1hour'.
If you write
SELECT * FROM wp_before_after
WHERE patientID = 8175
AND patient_display = 1
AND period_taken = '1hour'
you will compare the field periodtaken to a string (CHAR,VARCHAR,TEXT) equal to '1hour'.
I assume period_taken is a field typed CHAR,VARCHAR or TEXT
Before anything, DO NOT CONCATENATE SQL STRINGS nowadays it is a MUST (see how to do it properly https://stackoverflow.com/a/60496/3771219)
The problem you are facing is because, I presume, that the period_taken field is some sort of Char/Varchar/String field and when you are filtering by a "Stringy" field you must sorround your literals values with single quotes:
SELECT *
FROM wp_before_after
WHERE patientID = 8175
AND patient_display = 1
AND period_taken = '1hour'
Hope this help

LINQ to SQL with 'Contains' and an INT column. How do you make it work?

I'm trying to get this LINQ to SQL to work. The problem is parsedSeasons is a string like "1,2,3" and h.season is an int column. How can I get this to work correctly?
var id = (from h in db.t_ref_harvest_type
where parsedSeasons.Contains(h.season)
select new { h.id });
You need to first split your comma delimited string like this:
var Seasons = parsedSeasons.Split(',').Select(int.Parse);
Then use your LINQ query:
var id = (from h in db.t_ref_harvest_type
where Seasons.Contains(h.season)
select new { h.id });

SQL Server 2008: Error converting data type nvarchar to float

Presently troubleshooting a problem where running this SQL query:
UPDATE tblBenchmarkData
SET OriginalValue = DataValue, OriginalUnitID = DataUnitID,
DataValue = CAST(DataValue AS float) * 1.335
WHERE
FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5'
AND ZEGCodeID IN
(SELECT ZEGCodeID FROM tblZEGCode
WHERE(ZEGCode = 'C004') OR
(LEFT(ZEGParentCode, 4) = 'C004'))
Results in the following error:
Msg 8114, Level 16, State 5, Line 1
Error converting data type nvarchar to float.
The really odd thing is, if I change the UPDATE to SELECT to inspect the values that are retrieved are numerical values:
SELECT DataValue
FROM tblBenchmarkData
WHERE FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5'
AND ZEGCodeID IN
(SELECT ZEGCodeID
FROM tblZEGCode WHERE(ZEGCode = 'C004') OR
(LEFT(ZEGParentCode, 4) = 'C004'))
Here are the results:
DataValue
2285260
1205310
Would like to use TRY_PARSE or something like that; however, we are running on SQL Server 2008 rather than SQL Server 2012. Does anyone have any suggestions? TIA.
It would be helpful to see the schema definition of tblBenchmarkData, but you could try using ISNUMERIC in your query. Something like:
SET DataValue = CASE WHEN ISNUMERIC(DataValue)=1 THEN CAST(DataValue AS float) * 1.335
ELSE 0 END
Order of execution not always matches one's expectations.
If you set a where clause, it generally does not mean the calculations in the select list will only be applied to the rows that match that where. SQL Server may easily decide to do a bulk calculation and then filter out unwanted rows.
That said, you can easily write try_parse yourself:
create function dbo.try_parse(#v nvarchar(30))
returns float
with schemabinding, returns null on null input
as
begin
if isnumeric(#v) = 1
return cast(#v as float);
return null;
end;
So starting with your update query that's giving an error (please forgive me for rewriting it for my own clarity):
UPDATE B
SET
OriginalValue = DataValue,
OriginalUnitID = DataUnitID,
DataValue = CAST(DataValue AS float) * 1.335
FROM
dbo.tblBenchmarkData B
INNER JOIN dbo.tblZEGCode Z
ON B.ZEGCodeID = Z.ZEGCodeID
WHERE
B.FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5'
AND (
Z.ZEGCode = 'C004' OR
Z.ZEGParentCode LIKE 'C004%'
)
I think you'll find that a SELECT statement with exactly the same expressions will give the same error:
SELECT
OriginalValue,
DataValue NewOriginalValue,
OriginalUnitID,
DataUnitID OriginalUnitID,
DataValue,
CAST(DataValue AS float) * 1.335 NewDataValue
FROM
dbo.tblBenchmarkData B
INNER JOIN dbo.tblZEGCode Z
ON B.ZEGCodeID = Z.ZEGCodeID
WHERE
B.FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5'
AND (
Z.ZEGCode = 'C004' OR
Z.ZEGParentCode LIKE 'C004%'
)
This should show you the rows that can't convert:
SELECT
B.*
FROM
dbo.tblBenchmarkData B
INNER JOIN dbo.tblZEGCode Z
ON B.ZEGCodeID = Z.ZEGCodeID
WHERE
B.FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5'
AND (
Z.ZEGCode = 'C004' OR
Z.ZEGParentCode LIKE 'C004%'
)
AND IsNumeric(DataValue) = 0
-- AND IsNumeric(DataValue + 'E0') = 0 -- try this if the prior doesn't work
The trick in the last commented line is to tack on things to the string to force only valid numbers to be numeric. For example, if you wanted only integers, IsNumeric(DataValue + '.0E0') = 0 would show you those that aren't.

MySQL, select records with at least X characters matching

I am trying to accomplish the following. Let's say we have a table that contains these fields (ID, content)
1 | apple
2 | pineapple
3 | application
4 | nation
now, I am looking for a function that will tell me all possible common matches. For example, if the argument is "3", the function will return all possible strings from 3 characters that appear in more then one record.
In this case, I get "app","ppl","ple","ati","tio","ion"
If the argument is "4", i get: "appl","pple","atio","tion"
If the arugment is "5", i get: "apple","ation"
If the argument is "6", nohting is returned.
Untill now, I did not find a function that accomplishes this.
Thx!
Some extra information:
I am using this in a PHP script with a MySQL database. I really just want to give the amount of characters as an argument and of course the table to search in.
Well, this is kind of ugly, but it does work fine. It's generic SQL and will work in any environment. Simply generate a number of selects of a substring that is greater than the maximum length of the field that you're reading. Change the number 50 in the function to a number that exceeds your fieldlength. It may return a realllly long query, but like I said, it'll work fine. Here is an example in Python:
import sqlite3
c = sqlite3.connect('test.db')
c.execute('create table myTable (id integer, content varchar[50])')
for id, content in ((1,'apple'),(2,'pineapple'),(3,'application'),(4,'nation')):
c.execute('insert into myTable values (?,?)', [id,content])
c.commit();
def GenerateSQL(substrSize):
subqueries = ["select substr(content,%i,%i) AS substr, count(*) AS myCount from myTable where length(substr(content,%i,%i))=%i group by substr(content,%i,%i) " % (i,substrSize,i,substrSize,substrSize,i,substrSize) for i in range(50)]
sql = 'select substr FROM \n\t(' + '\n\tunion all '.join(subqueries) + ') \nGROUP BY substr HAVING sum(myCount) > 1'
return sql
print GenerateSQL(3)
print c.execute(GenerateSQL(3)).fetchall()
The query generated looks like:
select substr FROM
(select substr(content,0,3) AS substr, count(*) AS myCount from myTable where length(substr(content,0,3))=3 group by substr(content,0,3)
union all select substr(content,1,3) AS substr, count(*) AS myCount from myTable where length(substr(content,1,3))=3 group by substr(content,1,3)
union all select substr(content,2,3) AS substr, count(*) AS myCount from myTable where length(substr(content,2,3))=3 group by substr(content,2,3)
union all select substr(content,3,3) AS substr, count(*) AS myCount from myTable where length(substr(content,3,3))=3 group by substr(content,3,3)
union all select substr(content,4,3) AS substr, count(*) AS myCount from myTable where length(substr(content,4,3))=3 group by substr(content,4,3)
... )
GROUP BY substr HAVING sum(myCount) > 1
And the results it produces are:
[(u'app',), (u'ati',), (u'ion',), (u'nat',), (u'pin',), (u'ple',), (u'ppl',), (u'tio',)]
I'm sorry as I haven't been playing with php for a while & I don't have a proper test environment for it, but I quickly devised a way of doing this in c# 3.5
pseudocode: build a table with strings of the specified length & a count of occurences next to it. Select where count > 1:
static void Main(string[] args)
{
string[] data = { "apple", "pinapple", "application", "nation" };
string[] result = my_func(3,data);
foreach (string str in result)
{
Console.WriteLine(str);
}
Console.ReadKey();
}
private static string[] my_func(int l, string[] data)
{
Dictionary<string,int> dict = new Dictionary<string,int>();
foreach (string str in data)
{
for (int i = 0; i < str.Length - l + 1; i++)
{
string part = str.Substring(i, l);
if (dict.ContainsKey(part))
{
dict[part]++;
}else {
dict.Add(part,1);
}
}
}
var result = from k in dict.Keys
where dict[k] > 1
orderby dict[k] descending
select k;
return result.ToArray<string>();
}
One obvious option is to use REGEX. I have no prior experience in this but this might be of help to you:
http://dev.mysql.com/doc/refman/5.1/en/regexp.html
You'll need to find a suitable expression to match what you need.

What's the Linq to SQL equivalent to TOP or LIMIT/OFFSET?

How do I do this
Select top 10 Foo from MyTable
in Linq to SQL?
Use the Take method:
var foo = (from t in MyTable
select t.Foo).Take(10);
In VB LINQ has a take expression:
Dim foo = From t in MyTable _
Take 10 _
Select t.Foo
From the documentation:
Take<TSource> enumerates source and yields elements until count elements have been yielded or source contains no more elements. If count exceeds the number of elements in source, all elements of source are returned.
In VB:
from m in MyTable
take 10
select m.Foo
This assumes that MyTable implements IQueryable. You may have to access that through a DataContext or some other provider.
It also assumes that Foo is a column in MyTable that gets mapped to a property name.
See http://blogs.msdn.com/vbteam/archive/2008/01/08/converting-sql-to-linq-part-7-union-top-subqueries-bill-horst.aspx for more detail.
Use the Take(int n) method:
var q = query.Take(10);
The OP actually mentioned offset as well, so for ex. if you'd like to get the items from 30 to 60, you would do:
var foo = (From t In MyTable
Select t.Foo).Skip(30).Take(30);
Use the "Skip" method for offset.
Use the "Take" method for limit.
#Janei: my first comment here is about your sample ;)
I think if you do like this, you want to take 4, then applying the sort on these 4.
var dados = from d in dc.tbl_News.Take(4)
orderby d.idNews descending
select new
{
d.idNews,
d.titleNews,
d.textNews,
d.dateNews,
d.imgNewsThumb
};
Different than sorting whole tbl_News by idNews descending and then taking 4
var dados = (from d in dc.tbl_News
orderby d.idNews descending
select new
{
d.idNews,
d.titleNews,
d.textNews,
d.dateNews,
d.imgNewsThumb
}).Take(4);
no ? results may be different.
This works well in C#
var q = from m in MyTable.Take(10)
select m.Foo
Whether the take happens on the client or in the db depends on where you apply the take operator. If you apply it before you enumerate the query (i.e. before you use it in a foreach or convert it to a collection) the take will result in the "top n" SQL operator being sent to the db. You can see this if you run SQL profiler. If you apply the take after enumerating the query it will happen on the client, as LINQ will have had to retrieve the data from the database for you to enumerate through it
I do like this:
var dados = from d in dc.tbl_News.Take(4)
orderby d.idNews descending
select new
{
d.idNews,
d.titleNews,
d.textNews,
d.dateNews,
d.imgNewsThumb
};
You would use the Take(N) method.
Taking data of DataBase without sorting is the same as random take
Array oList = ((from m in dc.Reviews
join n in dc.Users on m.authorID equals n.userID
orderby m.createdDate descending
where m.foodID == _id
select new
{
authorID = m.authorID,
createdDate = m.createdDate,
review = m.review1,
author = n.username,
profileImgUrl = n.profileImgUrl
}).Take(2)).ToArray();
I had to use Take(n) method, then transform to list, Worked like a charm:
var listTest = (from x in table1
join y in table2
on x.field1 equals y.field1
orderby x.id descending
select new tempList()
{
field1 = y.field1,
active = x.active
}).Take(10).ToList();
This way it worked for me:
var noticias = from n in db.Noticias.Take(6)
where n.Atv == 1
orderby n.DatHorLan descending
select n;