I'll admit I'm kinda new at both Symfony and Doctrine but I can't find a way to join a table that has multiple details for each row on the starting table, so I only want the max(date) row out of that
The raw SQL would be something like
SELECT *
FROM users
JOIN activities on activities.user_id = users.id
and activity.date = (select max(date)
from activities a2
where a2.user_id = activites.user_id
and activities.date <= sysdate)
I've tried putting the RAW clause in the ->leftJoin method but it's not working
$query->leftJoin('p.activities', 'att', 'WITH', 'att.date = (select max(a2.date) from activities a2 where att.user_id = a2.user_id and a2.date< sysdate)');
this results in a
[Semantical Error] line 0, col 133 near 'activities a2 where': Error: Class 'activities' is not defined.
If I remove that where clause the join works fine though (but obviously returns too many rows)
Is there a way to do this with Doctrine? I can't convert the whole thing to raw SQL cause there are way more joins and conditions to apply after this (filtering results on a list page)
PS: I'm on Symfony 3.4, if that changes anything
Ok, it was as easy as defining the actual class instead of the table name, so \AppBundle\Entity\Activities
Changing that (and the name fields to the entity properties) fixed the error and works fine
Related
I have a query like this (simplified and anonymised):
SELECT
Department.id,
Department.name,
Department.manager_id,
Employee.name AS manager_name
FROM
Department
LEFT OUTER JOIN Employee
ON Department.manager_id = Employee.id;
The field Department.manager_id may be NULL. If it is non-NULL then it is guaranteed to be a valid id for precisely one row in the Employee table, so the OUTER JOIN is there just for the rows in the Department table where it is NULL.
Here is the problem: old instances of the database do not have this Department.manager_id column at all. In those cases, I would like the query to act as if the field did exist but was always NULL, so e.g. the manager_name field is returned as NULL. If the query only used the Department table then I could just use SELECT * and check for the column in my application, but the JOIN seems to make this impossible. I would prefer not to modify the database, partly so that I can load the database in read only mode. Can this be done just by clever adjustment of the query?
For completeness, here is an answer that does not require munging both possible schemas into one query (but still doesn't need you to actually do the schema migration):
Check for the schema version, and use that to determine which SELECT query to issue (i.e. with or without the manager_id column and JOIN) as a separate step. Here are a few possibilities to determine the schema version:
The ideal situation is that you already keep track of the schema by assigning version numbers to the schema and recording them in the database. Commonly this is done with either:
The user_version pragma.
A table called "Schema" or similar with one row containing the schema version number.
You can directly determine whether the column is present in the table. Two possibilities:
Use the table_info pragma to determine the list of columns in the table.
Use a simple SELECT * FROM Table LIMIT 1 and look at what columns are returned (this is probably better as it is independent of the database engine).
This seems to work:
SELECT
Dept.id,
Dept.name,
Dept.manager_id,
Employee.name AS manager_name
FROM
(SELECT *, NULL AS manager_id FROM Department) AS Dept
LEFT OUTER JOIN Employee
ON Dept.manager_id = Employee.id;
If the manager_id column is present in Department then it is used for the join, whereas if it is not then Dept.manager_id and Employee.name are both NULL.
If I swap the column order in the subquery:
(SELECT NULL AS manager_id, * FROM Department) AS Dept
then the Dept.manager_id and Employee.name are both NULL even if the Department.manager_id column exists, so it seems that Dept.manager_id refers to the first column in the Dept subquery that has that name. It would be good to find a reference in the SQLite documentation saying that this behaviour is guaranteed (or explicitly saying that it is not), but I can't find anything (e.g. in the SELECT or expression pages).
I haven't tried this with other database systems so I don't know if it will work with anything other than SQLite.
In drupal website we are getting sql query data exporting very slow (taking longtime) issue how to solve the issue
The query as follows
SELECT DISTINCT(a.*), c.nid, b.uac_inst_campus_cricos
FROM uac_export_coursetable_latest AS a
LEFT JOIN uac_institutiondata AS c
ON c.uac_institutiondata_institution = a.uac_course_institution
LEFT JOIN uac_inst_campus_latest AS b
ON b.nid = c.nid AND b.uac_inst_furtherinfobox_heading = a.campusname
WHERE a.uac_course_institution = '6628'
AND intyear12 = 'Yes'
ORDER BY uaccoursecode
Because we don't know the exact schema of your custom tables, we can't give you an exact solution but in general when query execution is slow, you need to verify the columns you are using for the JOINS and within the WHERE clausule.
Be sure that you are joining on foreign key columns
Be sure that indexes are set on the columns used within conditions
In your case, I would add index on following columns: uac_institutiondata_institution (uac_institutiondata table), intyear12 (uac_export_coursetable_latest), nid (uac_inst_campus_latest table)
If the uac_course_institution column in uac_export_coursetable_latest table is not a primary key, also on a index on this column.
More info about indexes on a MySql database: http://dev.mysql.com/doc/refman/5.0/en/create-index.html
I am currently using Symfony2 and Doctrine2 and am trying to join two tables together using query builder.
The problem I have is that all my annotated entities do not have the table relationships setup. I will at some point address this, but in the mean time I need to try and work round this.
Basically I have two tables: a product table and a product_description table. The product table stores the basic information and then I have a product_description table that stores the description information. A product can have one or more descriptions due to language.
I want to use query builder, so I can retrieve both the product and product_description results as objects.
At the moment I am using the following code:
// Get the query builder
$qb = $em->createQueryBuilder();
// Build the query
$qb->select(array('p, pd'));
$qb->from('MyCompanyMyBundle:Product', 'p');
$qb->innerJoin('pd', 'MyCompanyMyBundle:ProductDescription', 'pd', 'ON', $qb->expr()->eq('p.id', 'pd.departmentId'));
$query = $qb->getQuery();
$products = $query->getResult();
This gives me the following error:
[Syntax Error] line 0, col 71: Error: Expected Doctrine\ORM\Query\Lexer::T_DOT, got 'MyCompanyMyBundle:ProductDescription'
Can anyone point me in the right direction? I am up for doing it differently if there is an alternative.
Without having the relationships defined, I don't think you can join the tables. This is because when you use DQL, you're querying an object rather than a table, and if the objects are unaware of each other, you can't join them.
I think you should look at using a NativeQuery. From the docs:
A NativeQuery lets you execute native SELECT SQL statements, mapping the results according to your specifications. Such a specification that describes how an SQL result set is mapped to a Doctrine result is represented by a ResultSetMapping. It describes how each column of the database result should be mapped by Doctrine in terms of the object graph. This allows you to map arbitrary SQL code to objects, such as highly vendor-optimized SQL or stored-procedures.
Basically, you write raw SQL, but tell Doctrine how to map the results to your existing entities.
Hope this helps.
I need to delete rows from an SQLite table where their row IDs do not exist in another table. The SELECT statement returns the correct rows:
SELECT * FROM cache LEFT JOIN main ON cache.id=main.id WHERE main.id IS NULL;
However, the delete statement generates an error from SQLIte:
DELETE FROM cache LEFT JOIN main ON cache.id=main.id WHERE main.id IS NULL;
The error is: SQLite Error 1 - near "left": syntax error. Is there another syntax I could use?
SQLite apparently doesn't support joins with the delete statement, as you can see on the Syntax diagrams. You should however be able to use a subquery to delete them.
ie.
DELETE FROM cache WHERE id IN
(SELECT cache.id FROM cache LEFT JOIN main ON cache.id=main.id WHERE main.id IS NULL);
(Not tested)
Since you going down the route of subquery, might as well get rid of the join altogether and simplify the query:
DELETE FROM cache WHERE id NOT IN (SELECT id from main);
Solution from #wimvds didn't work for me, so I modified the query and removed WHERE condition:
DELETE FROM FirstTable WHERE firstTableId NOT IN (SELECT SecondTable.firstTableId FROM SecondTable LEFT JOIN FirstTable ON FirstTable.firstTableId=SecondTable.firstTableId)
This deletes all the rows from FirstTable that do not have their id assigned to any row in SecondTable.
I have a grid that displays lines from a table. Now, I have these two requirements:
Show only the lines that contains values in the "hour" fields. The "hour" field is an array type.
Show the lines from a project and its subproject
My problem is this: to meet requirement #1, I need to use a select statement in my datasource since I cannot access array value using QueryBuildDataSource (this is a known limitation in Dynamics AX).
But to meet requirements #2 I need to have two "exists join", and this is not possible in Dynamics AX. For example the following code would not work:
select from table where
exists join tableChild where projectId = MyProjectId OR
exists join tableChild where parentProjectId = MyProjectId
How would someone address this issue?
From the select statement example you provided, it appears it may not be necessary to have two exist joins. A single exists join with the "OR" for the two possible conditions in its where clauses may be sufficient, of course, you should still have some relationship between table and tableChild for the join to make logical sense.
select from table
exists join tableChild
where (tableChild.projectId = MyProjectId || tableChild.parentProjectId = MyProjectId)
You can use array values in query ranges providing field IDs using fieldID2Ext function.
You can build view and apply confitions on top of it.