CreateCriteria and MONTH - nhibernate

Is it possible to use MONTH in a CreateCriteria-statement?
Does NHibernate support YEAR and/or MONTH?
I have a sql-statement like
select obs2.Lopnr from Obs obs2 where MONTH(obs2.Datum)=11)
Best Regards from
Mats

ICriteria supports arbitrary SQL as a restriction. Therefore you could do:
var criteria = session.CreateCriteria(typeof(Obs))
.Add(Expression.Sql("MONTH({alias}.Datum) = ?", 11, NHibernateUtil.Int32);
var results = criteria.List<Obs>();
This will execute a SQL query with {alias} replaced by the alias that NHibernate is using for the Obs table. Of course, this limits your portablility to other databases, as SQL is now embedded in your query.
Another thing to remember is that the names you're using here are the mapped property and class names, not the underlying column and table names.

I don't believe it's possible in a criteria statement. The date functions (year, month, day) are supported in HQL queries so they are usable in that way.

Related

Using Spring JPA Select DISTINCT

I am having problems using spring jpa using a Distinct. My goal it's to return the whole object, instead just the field that pass to "Distinct".
Example:
This is my table:
And I want to Distinct the "Test_ID" where FLOW_ID = 345
So I am doing this:
Page findTestIdDistinctByFlowId(Pageable pageable, String FlowID);
Instead of this (my goal):
Any advice? Another option?
Distinct doesn't apply on a column or select expression it operates on a row in SQL or an entity in JPA.
Since the returned IDs differ the rows are not distinct and get all returned.
I suspect you could achieve what you want with an explicitly written SQL or JPQL statement. But I'm not at all clear what the actual criteria is that you want to use.

Count non null values in multiple columns with LINQ

The following SQL query counts non-null values of multiple columns in a single query (as in this answer):
SELECT COUNT(Id) AS Total,
COUNT(Column_1) AS Column_1_Non_Null_Count,
COUNT(Column_2) AS Column_2_Non_Null_Count,
COUNT(Column_3) AS Column_3_Non_Null_Count,
...
FROM MyTable
Is there a corresponding Linq query which executes a SQL query similar to this one (without a subquery for each column count)?
Counting null values instead of non-null values would also be ok.
I'm not sure that exist a good way to do it with Entity Framework, I think that is better to do it with raw sql.
But assuming that you want to do it with Entity Framework, may be one way to do it is creating several queries using FutureCount method from EF.Extended library. Using Future methods from EF.Extended, all queries are postponed until is accessed the result of one of the queries and the data will be retrieved in one round trip to the database server.
var queryColumn1 = MyDBContext.MyTable.Where(q => q.Column1 == null).FutureCount();
var queryColumn2 = MyDBContext.MyTable.Where(q => q.Column2 == null).FutureCount();
...
int countColumn1 = queryColumn1.Value;
int countColumn2 = queryColumn2.Value
What I dislike of this solution is the readibility of the code, as I said I think that the good approach is do it using raw sql or using a stored procedured

Converting SQL statement to SQL expression field in Crystal Reports

I have a SQL statement that pulls data I need but I can't get the syntax right in Crystal Reports.
This statement works in SQL:
SELECT
max([meter_reading])
FROM [Forefront].[dbo].[EC_METER_HISTORY_MC]
WHERE [Meter_Number] = '1' AND [Transaction_Date] < '20130101'
GROUP BY
[Company_Code], [Equipment_Code], [Meter_Number]
This is what I changed it to in crystal but I can't get the right syntax.
SELECT
Maximum({EC_METER_HISTORY_MC.meter_reading})
FROM [EC_METER_HISTORY_MC]
WHERE {EC_METER_HISTORY_MC.Meter_Number} = '1'
AND {EC_METER_HISTORY_MC.Transaction_Date} < {1?Startdate}
GROUP BY {EC_METER_HISTORY_MC.Company_Code}
,{EC_METER_HISTORY_MC.Equipment_Code}
,{EC_METER_HISTORY_MC.Meter_Number}
Your first step should be reading up on how SQL Expressions work in Crystal. Here is a good link to get you started.
A few of your problems include:
Using a parameter field. SQL Expressions are not compatible with CR
parameters and cannot be used in them.
SQL Expressions can only return scalar values per row of your report. That means that your
use of GROUP BY doesn't serve any purpose.
Your use of curly braces means that you're referencing those fields in the main report query instead of in the subquery you're trying to create with this expression.
Here's a simplified example that would find the max meter reading of a particular meter (for Oracle since that's what I know and you didn't specify which DB you're using):
case when {EC_METER_HISTORY_MC.Meter_Number} is null then null
else (select max(Meter_Reading)
from EC_METER_HISTORY_MC
where Meter_Number={EC_METER_HISTORY_MC.Meter_Number} --filter by the meter number from main query
and Transaction_Date < Current_Date) --filter by some date. CAN'T use parameter here.
end
You can't use parameter fields in a SQL Expression, sadly. Perhaps you can correlate the Transaction_Date to a table in the main query. Otherwise, I would suggest using a Command.
You have two options for the Command:
Use a single Command object as the data source for the whole report--which involves (potentially) a fair amount of rework.
Add a Command to the existing table set (in the Database 'Expert'). Link it to other tables as desired. This will perform a second SELECT and join the results in memory (WhileReadingRecords, if I'm not mistaken). The slight performance hit may we worth the benefit.

Is there a UniData SQL equivalent to the UniQuery SAMPLE keyword?

I'm using UniData 6. Is there a UniData SQL equivalent to the UniQuery SAMPLE keyword?
Using UniQuery, I've always been able to do:
SELECT CUST BY NAME SAMPLE 1
and it would give me the record with the first alphabetical name.
In UniData SQL, I'd like to be able to do something like:
SELECT NAME FROM CUST ORDER BY NAME SAMPLE 1;
...or, as in other SQL databases...
SELECT TOP 1 NAME FROM CUST ORDER BY NAME;
and get just the name of the the customer who's listed first alphabetically. Is there a keyword like this?
Unfortunately, no, there does not appear to be a UniSQL equivalent to the UniQuery SAMPLE keyword. UniSQL consists of a subset of ANSI SQL-92 standards, with some extensions to support multivalue. However, ANSI SQL-92 does not contain a standard for limiting the result set returned from a query, which is why various DBMS have different syntax for doing so.
ANSI SQL-2008 added the FETCH FIRST clause which is the standard way of implementing a limit to the number of rows returned by a query. It would require a pretty significant update to bring UniSQL up to recent standards since it is now 20+ years behind. There doesn't seem to be significant enough demand in the user community to undertake that effort.
Depending on your file's schema, you may be able to apply a workaround. If you are using an auto-incrementing key, you could use a syntax such as:
SELECT foo
FROM bar
WHERE #ID <= 10
The above query would be apply a de facto limit to the number of rows returned.
SELECT will usually only apply to record IDs. If you want to list out attributes, try LIST: LIST INVENTORY PROD_NAME PRICE QTY SAMPLE for instance will return the first 10 product names, prices and quantities.

Use SELECT inside an UPDATE query

How can I UPDATE a field of a table with the result of a SELECT query in Microsoft Access 2007.
Here's the Select Query:
SELECT Min(TAX.Tax_Code) AS MinOfTax_Code
FROM TAX, FUNCTIONS
WHERE (((FUNCTIONS.Func_Pure)<=[Tax_ToPrice]) AND ((FUNCTIONS.Func_Year)=[Tax_Year]))
GROUP BY FUNCTIONS.Func_ID;
And here's the Update Query:
UPDATE FUNCTIONS
SET FUNCTIONS.Func_TaxRef = [Result of Select query]
Well, it looks like Access can't do aggregates in UPDATE queries. But it can do aggregates in SELECT queries. So create a query with a definition like:
SELECT func_id, min(tax_code) as MinOfTax_Code
FROM Functions
INNER JOIN Tax
ON (Functions.Func_Year = Tax.Tax_Year)
AND (Functions.Func_Pure <= Tax.Tax_ToPrice)
GROUP BY Func_Id
And save it as YourQuery. Now we have to work around another Access restriction. UPDATE queries can't operate on queries, but they can operate on multiple tables. So let's turn the query into a table with a Make Table query:
SELECT YourQuery.*
INTO MinOfTax_Code
FROM YourQuery
This stores the content of the view in a table called MinOfTax_Code. Now you can do an UPDATE query:
UPDATE MinOfTax_Code
INNER JOIN Functions ON MinOfTax_Code.func_id = Functions.Func_ID
SET Functions.Func_TaxRef = [MinOfTax_Code].[MinOfTax_Code]
Doing SQL in Access is a bit of a stretch, I'd look into Sql Server Express Edition for your project!
I wrote about some of the limitations of correlated subqueries in Access/JET SQL a while back, and noted the syntax for joining multiple tables for SQL UPDATEs. Based on that info and some quick testing, I don't believe there's any way to do what you want with Access/JET in a single SQL UPDATE statement. If you could, the statement would read something like this:
UPDATE FUNCTIONS A
INNER JOIN (
SELECT AA.Func_ID, Min(BB.Tax_Code) AS MinOfTax_Code
FROM TAX BB, FUNCTIONS AA
WHERE AA.Func_Pure<=BB.Tax_ToPrice AND AA.Func_Year= BB.Tax_Year
GROUP BY AA.Func_ID
) B
ON B.Func_ID = A.Func_ID
SET A.Func_TaxRef = B.MinOfTax_Code
Alternatively, Access/JET will sometimes let you get away with saving a subquery as a separate query and then joining it in the UPDATE statement in a more traditional way. So, for instance, if we saved the SELECT subquery above as a separate query named FUNCTIONS_TAX, then the UPDATE statement would be:
UPDATE FUNCTIONS
INNER JOIN FUNCTIONS_TAX
ON FUNCTIONS.Func_ID = FUNCTIONS_TAX.Func_ID
SET FUNCTIONS.Func_TaxRef = FUNCTIONS_TAX.MinOfTax_Code
However, this still doesn't work.
I believe the only way you will make this work is to move the selection and aggregation of the minimum Tax_Code value out-of-band. You could do this with a VBA function, or more easily using the Access DLookup function. Save the GROUP BY subquery above to a separate query named FUNCTIONS_TAX and rewrite the UPDATE statement as:
UPDATE FUNCTIONS
SET Func_TaxRef = DLookup(
"MinOfTax_Code",
"FUNCTIONS_TAX",
"Func_ID = '" & Func_ID & "'"
)
Note that the DLookup function prevents this query from being used outside of Access, for instance via JET OLEDB. Also, the performance of this approach can be pretty terrible depending on how many rows you're targeting, as the subquery is being executed for each FUNCTIONS row (because, of course, it is no longer correlated, which is the whole point in order for it to work).
Good luck!
I had a similar problem. I wanted to find a string in one column and put that value in another column in the same table. The select statement below finds the text inside the parens.
When I created the query in Access I selected all fields. On the SQL view for that query, I replaced the mytable.myfield for the field I wanted to have the value from inside the parens with
SELECT Left(Right(OtherField,Len(OtherField)-InStr((OtherField),"(")),
Len(Right(OtherField,Len(OtherField)-InStr((OtherField),"(")))-1)
I ran a make table query. The make table query has all the fields with the above substitution and ends with INTO NameofNewTable FROM mytable
Does this work? Untested but should get the point across.
UPDATE FUNCTIONS
SET Func_TaxRef =
(
SELECT Min(TAX.Tax_Code) AS MinOfTax_Code
FROM TAX, FUNCTIONS F1
WHERE F1.Func_Pure <= [Tax_ToPrice]
AND F1.Func_Year=[Tax_Year]
AND F1.Func_ID = FUNCTIONS.Func_ID
GROUP BY F1.Func_ID;
)
Basically for each row in FUNCTIONS, the subquery determines the minimum current tax code and sets FUNCTIONS.Func_TaxRef to that value. This is assuming that FUNCTIONS.Func_ID is a Primary or Unique key.
I did want to add one more answer that utilizes a VBA function, but it does get the job done in one SQL statement. Though, it can be slow.
UPDATE FUNCTIONS
SET FUNCTIONS.Func_TaxRef = DLookUp("MinOfTax_Code", "SELECT
FUNCTIONS.Func_ID,Min(TAX.Tax_Code) AS MinOfTax_Code
FROM TAX, FUNCTIONS
WHERE (((FUNCTIONS.Func_Pure)<=[Tax_ToPrice]) AND ((FUNCTIONS.Func_Year)=[Tax_Year]))
GROUP BY FUNCTIONS.Func_ID;", "FUNCTIONS.Func_ID=" & Func_ID)
I know this topic is old, but I thought I could add something to it.
I could not make an Update with Select query work using SQL in MS Access 2010. I used Tomalak's suggestion to make this work. I had a screenshot, but am apparently too much of a newb on this site to be able to post it.
I was able to do this using the Query Design tool, but even as I was looking at a confirmed successful update query, Access was not able to show me the SQL that made it happen. So I could not make this work with SQL code alone.
I created and saved my select query as a separate query. In the Query Design tool, I added the table I'm trying to update the the select query I had saved (I put the unique key in the select query so it had a link between them). Just as Tomalak had suggested, I changed the Query Type to Update. I then just had to choose the fields (and designate the table) I was trying to update. In the "Update To" fields, I typed in the name of the fields from the select query I had brought in.
This format was successful and updated the original table.