SQL “Row values” syntax in WHERE clause with JPA Criteria API - jpa-2.0

Is it possible with Criteria API to generate WHERE clause with "row values"?
Like this
SELECT * FROM t1 WHERE (column1,column2) < (1,1);
Use case: let's say we can receive from a client a parameter list of variable length.
If client send one param A then I want to generate e.g SELECT * FROM t1 WHERE c1 < ?
If client send two params A and B then SELECT * FROM t1 WHERE c1 < ? OR ((c1 = ?) AND (c2 < ?))
and so on up to N parameters.
Definitely, I can implement this logic using Criteria's and, or etc. methods, but with "row values" syntax an implementation would be much simpler.
So, my question is whether there is some method(s) in Criteria API which helps to build SQL with row values syntax

Related

Query Drupal 8 content types with expression

In short, I need to do an entity query while running an expression. I can't find any way to accomplish this. I'm assuming there should be two ways.
An entity query with an expression - When I try this I can't get any expressions to work
a raw DB query, but I'm not familiar with how to join all the fields related to the content type of nodes I need.
Here is a shorthand example of what I need to accomplish
X = content type
y = field on x content type
z = field on x content type
My expression below is just an example, but need to run this in the database query
- Select y and z from x
- if x > y return node id
Any help would be great. This is going to run on a very large dataset, trying to find the fastest way to do the query in the database.
Comparing two fields is not possible using the entity query.
To do this, you may need to use the more low level Dynamic Queries and its where method:
$query = \Drupal::database()->select('node_field_data', 'n');
$query->condition('n.type', 'x'); // to get content type x
$query->innerJoin('node__field_y', 'y', 'y.entity_id = n.nid'); // join with field y
$query->innerJoin('node__field_z', 'z', 'z.entity_id = n.nid'); // join with field z
$query->where('z.field_z_value > y.field_y_value'); // your condition
$query->addField('n', 'nid'); // get node id in result
$results = $query->execute()->fetchAllKeyed(0, 0);

array in prepared statement inside where in clause

prep_stmt = con->prepareStatement("SELECT * FROM table WHERE customers in ( ? ) and alive = ?");
prep_stmt->setString(1,customer_string);
prep_stmt->setInt(2,1);
res = prep_stmt->executeQuery();
Here the customer_string is "12,1,34,67,45,14"
When I pass it as a String it always returns a single row, takes the first value only 12.
The sql statement prepared is:
SELECT * FROM table WHERE customers in ( "12,1,34,67,45,14" ) and alive = 1
but I want sql statement to be prepared as:
SELECT * FROM table WHERE customers in (12,1,34,67,45,14 ) and alive = 1
What is the easiest way to achieve the same in C++?
I am assuming you are using the MySQL C++ Connector. Unfortunately it seems that it is not possible to pass array as parameter of prepared statement using this API:
Connector/C++ does not support the following JDBC standard data types: ARRAY, BLOB, CLOB, DISTINCT, FLOAT, OTHER, REF, STRUCT.
https://dev.mysql.com/doc/connector-cpp/en/connector-cpp-usage-notes.html
You can place the value into the query directly by concatenating strings. Be VERY careful to not introduce SQL injection vulnerability. Alternatively use some other API.

Update a table by using multiple joins

I am using Java DB (Java DB is Oracle's supported version of Apache Derby and contains the same binaries as Apache Derby. source: http://www.oracle.com/technetwork/java/javadb/overview/faqs-jsp-156714.html#1q2).
I am trying to update a column in one table, however I need to join that table with 2 other tables within the same database to get accurate results (not my design, nor my choice).
Below are my three tables, ADSID is a key linking Vehicles and Customers and ADDRESS and ZIP in Salesresp are used to link it to Customers. (Other fields left out for the sake of brevity.)
Salesresp(address, zip, prevsale)
Customers(adsid, address, zipcode)
Vehicles(adsid, selldate)
The goal is to find customers in the SalesResp table that have previously purchased a vehicle before the given date. They are identified by address and adsid in Customers and Vechiles respectively.
I have seen updates to a column with a single join and in fact asked a question about one of my own update/joins here (UPDATE with INNER JOIN). But now I need to take it that one step further and use both tables to get all the information.
I can get a multi-JOIN SELECT statement to work:
SELECT * FROM salesresp
INNER JOIN customers ON (SALESRESP.ZIP = customers.ZIPCODE) AND
(SALESRESP.ADDRESS = customers.ADDRESS)
INNER JOIN vehicles ON (Vehicles.ADSId =Customers.ADSId )
WHERE (VEHICLES.SELLDATE<'2013-09-24');
However I cannot get a multi-JOIN UPDATE statement to work.
I have attempted to try the update like this:
UPDATE salesresp SET PREVSALE = (SELECT SALESRESP.address FROM SALESRESP
WHERE SALESRESP.address IN (SELECT customers.address FROM customers
WHERE customers.adsid IN (SELECT vehicles.adsid FROM vehicles
WHERE vehicles.SELLDATE < '2013-09-24')));
And I am given this error: "Error code 30000, SQL state 21000: Scalar subquery is only allowed to return a single row".
But if I change that first "=" to a "IN" it gives me a syntax error for having encountered "IN" (Error code 30000, SQL state 42X01).
I also attempted to do more blatant inner joins, but upon attempting to execute this code I got the the same error as above: "Error code 30000, SQL state 42X01" with it complaining about my use of the "FROM" keyword.
update salesresp set prevsale = vehicles.selldate
from salesresp sr
inner join vehicles v
on sr.prevsale = v.selldate
inner join customers c
on v.adsid = c.adsid
where v.selldate < '2013-09-24';
And in a different configuration:
update salesresp
inner join customer on salesresp.address = customer.address
inner join vehicles on customer.adsid = vehicles.ADSID
set salesresp.SELLDATE = vehicles.selldate where vehicles.selldate < '2013-09-24';
Where it finds the "INNER" distasteful: Error code 30000, SQL state 42X01: Syntax error: Encountered "inner" at line 3, column 1.
What do I need to do to get this multi-join update query to work? Or is it simply not possible with this database?
Any advice is appreciated.
If I were you I would:
1) Turn off autocommit (if you haven't already)
2) Craft a select/join which returns a set of columns that identifies the record you want to update E.g. select c1, c2, ... from A join B join C... WHERE ...
3) Issue the update. E.g. update salesrep SET CX = cx where C1 = c1 AND C2 = c2 AND...
(Having an index on C1, C2, ... will boost performance)
4) Commit.
That way you don't have worry about mixing the update and the join, and doing it within a txn ensures that nothing can change the result of the join before your update goes through.

How to write a DQL select statement to search some, but not all the entities in a single table inheritance table

So I have 3 entities within one table. I need to be able to search 2 out of the 3 entities in one select statement, but I'm not sure how to do this.
Use the INSTANCE OF operator in your dql query like this (where User is your base class):
$em->createQuery('
SELECT u
FROM Entity\User u
WHERE (u INSTANCE OF Entity\Manager OR u INSTANCE OF Entity\Customer)
');
Doctrine translates this in the sql query in a WHERE user.type = '...' condition.
See here for more details on the dql query syntax.
The answer for multiple instances actually doesn't work. You would have to do something like this to check for multiple instances.
$classes = ['Entity\Manager', 'Entity\Customer'];
$qb = $this->createQueryBuilder('u');
->where('u.id > 10') //an arbitrary condition, to show it can be combined with multiple instances tests
->andWhere("u INSTANCE OF ('" . implode("','", $classes) . "')");
As commented by flu, if you want to retrieve some entities from different instances with a QueryBuilder instead of a DQL query, you can use an array as parameter:
$qb = $this->createQueryBuilder('u');
->where('u.id > 10') //an arbitrary condition, to show it can be combined with multiple instances tests
->andWhere('u INSTANCE OF :classes')
->setParameter('classes', ['Entity\Manager', 'Entity\Customer'])
;

From a one to many SQL dataset Can I return a comma delimited list in SSRS?

I am returning a SQL dataset in SSRS (Microsoft SQL Server Reporting Services) with a one to many relationship like this:
ID REV Event
6117 B FTG-06a
6117 B FTG-06a PMT
6117 B GTI-04b
6124 A GBI-40
6124 A GTI-04b
6124 A GTD-04c
6136 M GBI-40
6141 C GBI-40
I would like to display it as a comma-delimited field in the last column [Event] like so:
ID REV Event
6117 B FTG-06a,FTG-06a PMT,GTI-04b
6124 A GBI-40, GTI-04b, GTD-04c
6136 M GBI-40
6141 C GBI-40
Is there a way to do this on the SSRS side of things?
You want to concat on the SQL side not on the SSRS side, that way you can combine these results in a stored procedure say, and then send it to the reporting layer.
Remember databases are there to work with the data. The report should just be used for the presentation layer, so there is no need to tire yourself with trying to get a function to parse this data out.
Best thing to do is do this at the sproc level and push the data from the sproc to the report.
Based on your edit this is how you would do it:
To concat fields take a look at COALESCE.
You will then get a string concat of all the values you have listed.
Here's an example:
use Northwind
declare #CategoryList varchar(1000)
select #CategoryList = coalesce(#CategoryList + ‘, ‘, ”) + CategoryName from Categories
select ‘Results = ‘ + #CategoryList
Now because you have an additional field namely the ID value, you cannot just add on values to the query, you will need to use a CURSOR with this otherwise you will get a notorious error about including additional fields to a calculated query.
Take a look here for more help, make sure you look at the comment at the bottom specifically posted by an 'Alberto' he has a similiar issue as you do and you should be able to figure it out using his comment.