I have a table Item with the following columns:
Id
Category
value
date
I build a SQL request which returns all the lines with the latest date for each category:
SELECT *
FROM item i
WHERE (i.category, i.date) IN (SELECT category, MAX(date)
FROM item
GROUP BY category)
This works fine and returns what I need.
I work with Symfony2 and Doctrine, so I would prefer to use DQL (or even better: the QueryBuilder) instead of NativeSQL.
So here is my DQL request :
SELECT i
FROM MyBundle:Item i
WHERE (i.category, i.date) IN (SELECT i2.category, MAX(i2.date)
FROM MyBundle:Item i2
GROUP BY i2.category
)
Which gives me the error:
QueryException: [Syntax Error] line 0, col 103: Error: Expected Doctrine\ORM\Query\Lexer::T_CLOSE_PARENTHESIS, got ','
If I remove the first couple of parenthesis, I get :
QueryException: [Syntax Error] line 0, col 102: Error: Expected =, <, <=, <>, >, >=, !=, got ','
I thought there was a problem with the WHERE so I tried the following just to see what would happen:
SELECT i
FROM MyBundle:Item i
WHERE i IN (SELECT i2.category, MAX(i2.date)
FROM MyBundle:Item i2
GROUP BY i2.category
)
I get:
QueryException: [Syntax Error] line 0, col 116: Error: Expected Doctrine\ORM\Query\Lexer::T_FROM, got ','
But in the doctrine doc, there is an example with several columns after the SELECT, using this same syntax!
Do you have any idea where does my problem come from?
Thank you!
Regards,
You could use exists:
SELECT
i
FROM
MyBundle:Item i
WHERE
EXISTS (
SELECT i2
FROM MyBundle:Item i2
WHERE i2.category = i.category
GROUP BY i2.category
HAVING MAX(i2.date) = i.date
)
You will need to separate the query's conditional statements; This is because DQL is unable to parse the comma separated field names (i.category, i.date).
SELECT
i
FROM
MyBundle:Item i
WHERE
i.category IN ( (SELECT i2.category FROM MyBundle:Item i2 GROUP BY i2.specy) )
AND
i.date IN ( (SELECT MAX(i2.date) FROM MyBundle:Item i2 GROUP BY i2.specy) )
I would also recommend using parentheses () to wrap any sub queries.
Related
I have a simple case like here, anyone can help?
I have two table here COMPLAINT and HANDLING now i want to select from those table with 2 condition where in HANDLING table is null, and date from COMPLAINT is more than 5 days from sysdate.
If I use SQL code like this, it will be error :
You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near 'CASE WHEN B.CID IS NULL AND (SELECT SYSDATE FROM DUAL)-
A.SUBMIT_DATE > 5 TH' at line 2
SELECT * FROM complaint a LEFT JOIN handling b ON a.cid=b.cid
CASE
WHEN B.CID IS NULL AND (SELECT SYSDATE FROM DUAL)- A.`SUBMIT_DATE` > 5
THEN 'OVER'
ELSE 'CLEAR'
END
The case statement you have added is in the wrong place and you can not use it in the joining clause as you are doing.
However if you want select something using case when then it must be in the select clause something as
select
*,
case
when b.cid is null and datediff(curdate(),a.SUBMIT_DATE) > 5 then 'OVER'
else 'CLEAR'
end as `some_col_name`
from complaint a LEFT JOIN handling b ON a.cid=b.cid
Case statement must be in select and not after join as below :
SELECT *,
CASE
WHEN B.CID IS NULL AND datediff(curdate(), a.SUBMIT_DATE) > 5
THEN 'OVER'
ELSE 'CLEAR'
END AS 'YOUR_COL'
FROM complaint a LEFT JOIN handling b ON a.cid=b.cid
i want use a subquery in a main query like following:
SELECT distinct(cnt.crid),cu.companyName,m.*,cnt.*,m.submitDate as mSubmitDate
from tbl_mahmoleh m,tbl_customer cu,tbl_cntreserve cnt
where m.cuID=cu.cuID and m.mBLID=cnt.mBLID and m.cuID='12'
and (cnt.crID IN (SELECT DISTINCT(crID) FROM tbl_paymentcnt))
and (cnt.crID IN (SELECT pc.crID, SUM( amount ) AS PaySum
FROM tbl_paymentcnt pc GROUP BY pc.crID HAVING PaySum < '2000'))
ORDER BY inputDateD
but i faced by this error
Blockquote #1241 - Operand should contain 1 column(s)
i got it, the IN clause can't work with more than one field, i changed my Query to the following and my Problem was solved.
SELECT DISTINCT(cnt.crid),cu.companyName,m.*,cnt.*,m.submitDate AS mSubmitDate
FROM tbl_mahmoleh m,tbl_customer cu,tbl_cntreserve cnt
WHERE m.cuID=cu.cuID AND m.mBLID = cnt.mBLID AND m.cuID = '12'
AND (cnt.crID IN (SELECT DISTINCT(crID) FROM tbl_paymentcnt))
AND (cnt.crID IN (SELECT pc.crID FROM tbl_paymentcnt pc GROUP BY pc.crID HAVING SUM(amount) < '2500'))
ORDER BY inputDateD
I'm using Symfony2 with Doctrine 2 and i'm creating a Query for the Pagerfanta Bundle for Symfony 2.
The Query is the following:
$qb = $this->createQueryBuilder('t')
->select()
->join('t.pois', 'p');
$qb->groupBy('t.id');
$qb->addOrderBy('count(case when p.image = 1 then 1 else null end)', 'DESC');
Which will give out the following Query:
SELECT t FROM Bundle\Entity\Turn t INNER JOIN t.pois p GROUP BY t.id ORDER BY count(case when p.image = 1 then 1 else null end) DESC
I also created a MySQL Query first so i can rebuild it in Doctrine 2 which looks like this:
SELECT *
FROM `turn`
LEFT JOIN (
poi
) ON ( turn.id = poi.turn_id )
GROUP BY turn.id
ORDER BY count( case when poi.image = 1 then 1 else null end) DESC;
This native Query works perfectly fine, tested in phpmyadmin.
But the Doctrine 2 Query throwes this exeptions:
Twig_Error_Runtime: An exception has been thrown during the rendering of a template ("[Syntax Error] line 0, col 115: Error: Expected end of string, got '('") in Bundle:Admin:showTurnsFiltered.html.twig at line 64.
QueryException: [Syntax Error] line 0, col 115: Error: Expected end of string, got '('
What am i doing wrong? Or is the Pagerfanta bundle not able to work with this Query?
I fixed this by adding a column to the turn Entity (count_poi) and filling it via native SQL.
After that the Query is the following:
SELECT *
FROM `turn`
ORDER BY t.count_poi DESC;
BUT it's just a workaround, i'm not happy with it, but it works for now
I have a query to select all proposals that are not voted ProProposalBundle:Proposal\Vote. There may exist a "not_voted" value in v.decision, or may not. That's why I used NOT EXIST.
SELECT p
FROM ProProposalBundle:Proposal p
INNER JOIN ProProposalBundle:Proposal\Vote v
WITH v.proposal = p
AND (v.decision = 'not_voted' OR NOT EXISTS (SELECT v FROM v WHERE v.user = {$user}))
WHERE p.community = {$community}
but it returns me an error:
[Semantical Error] line 0, col 181 near 'v WHERE v.user': Error: Class 'v' is not defined.
and it's related to the NOT EXISTS part, where v is theoretically defined before. I've also tried to do:
... NOT EXISTS (SELECT v FROM ProProposalBundle:Proposal\Vote v WHERE v.user = {$user}))
but now I'm getting:
[Semantical Error] line 0, col 220 near 'v WHERE v.user': Error: 'v' is already defined.
Any idea of what I am doing wrong?
try
NOT EXISTS (SELECT * FROM ProProposalBundle:Proposal\Vote v WHERE v.user = {$user}))
In the following query am trying to get one image per category
SELECT l.*
FROM (
SELECT id AS category_id,
COALESCE(
(
SELECT *
FROM images li
WHERE li.category_id = dlo.id
ORDER BY
li.save_status DESC, li.category_id DESC, li.id DESC
LIMIT 1
), 0) AS mid
FROM cats_imgs dlo where id='1'
) lo
JOIN images l
ON l.save_status = '3'
AND l.category_id >= lo.category_id
AND l.category_id <= lo.category_id
AND l.id >= lo.mid
but keep getting the following error :
#1241 - Operand should contain 1 column(s)
Any ideas ?
replace * with a single column for images li
I had a similar problem. Your 3rd level select statement (SELECT * FROM images li) needs to return a single value, since the 2nd level select statement (SELECT id AS category_id,COALESCE( ...) is expecting only one value in its place holder.
For my case, it worked. Here I also averaged the data from a second based table (SecondBasis) to the values in the one minute basis table (MinuteBasis):
SELECT MinuteBasis.time, MinuteBasis.avg_t, MinuteBasis.avg_p,MinuteBasis.avg_t2,
(SELECT avg(SecondBasis.m1)
FROM SecondBasis
WHERE SecondBasis.time BETWEEN MinuteBasis.time AND addtime (MinuteBasis.time,'0 0:00:59'))
(SELECT avg(SecondBasis.m2)
FROM SecondBasis
WHERE SecondBasis.time BETWEEN MinuteBasis.time AND addtime (MinutBasis.time,'0 0:00:59'))
FROM MinuteBasis
WHERE MinuteBasis.time BETWEEN '2012-05-02 8:30:00' AND '2012-05-02 8:44:59' ;