Unknown column in on clause - in query converted from SQL to HQL - mysql

I'm using Hibernate 4.3.11 and MySQL 5.7.11.
I wanted to rewrite this MySQL query to HQL:
SELECT COALESCE(g1.id, g2.id) as id, COALESCE(g1.type, g2.type) as type, COALESCE(g1.email_id, g2.email_id) as email_id, COALESCE(g1.url_id, g2.url_id) as url_id FROM notifications n
LEFT JOIN emails ON emails.id = n.email_id
LEFT JOIN urls ON urls.id = n.url_id
LEFT JOIN notifications_group g1 ON g1.email_id = n.email_id
LEFT JOIN notifications_group g2 ON g2.url_id = n.url_id
WHERE (((n.type = 'EMAIL' OR n.type = 'REMINDER') AND n.email_id is not null AND emails.user_id = :userId)
OR (n.type = 'URL' AND n.url_id is not null AND urls.user_id = :userId))
AND (g1.id is not null OR g2.id is not null)
AND ((g1.id is not null AND g1.id < :beforeId) OR (g2.id is not null AND g2.id < :beforeId))
GROUP BY COALESCE(g1.id, g2.id)
ORDER BY MAX(n.id) DESC
I have rewritten this native query to HQL:
SELECT COALESCE(g1.id, g2.id), COALESCE(g1.type, g2.type), COALESCE(g1.email, g2.email), COALESCE(g1.url, g2.url) FROM Notification n
LEFT JOIN n.email e
LEFT JOIN n.url u
LEFT JOIN e.notificationGroup g1
LEFT JOIN u.notificationGroup g2
WHERE (((n.type = delimail.enums.NotificationType.EMAIL OR n.type = delimail.enums.NotificationType.REMINDER) AND e IS NOT NULL AND e.user = :user)
OR (n.type = delimail.enums.NotificationType.URL AND u IS NOT NULL AND u.user = :user))
AND (g1 IS NOT NULL OR g2 IS NOT NULL)
AND ((g1.id IS NOT NULL AND g1.id < :beforeId) OR (g2 IS NOT NULL AND g2.id < :beforeId))
GROUP BY COALESCE(g1.id, g2.id), COALESCE(g1.type, g2.type), COALESCE(g1.email, g2.email), COALESCE(g1.url, g2.url)
ORDER BY MAX(n.id)
But it don't work. Hibernate generates this query:
SELECT coalesce(notificati3_.id, notificati4_.id) AS col_0_0_,
coalesce(notificati3_.type, notificati4_.type) AS col_1_0_,
coalesce(notificati3_.email_id, notificati4_.email_id) AS col_2_0_,
coalesce(notificati3_.url_id, notificati4_.url_id) AS col_3_0_
FROM delimail.notifications notificati0_
LEFT OUTER JOIN delimail.emails email1_ ON notificati0_.email_id=email1_.id
LEFT OUTER JOIN delimail.notifications_group notificati3_ ON email1_.id=notificati3_.email_id,
delimail.emails email5_, --l 8
delimail.urls url7_ --l 9
LEFT OUTER JOIN delimail.urls url2_ ON notificati0_.url_id=url2_.id --error: Unknown column 'notificati0_.url_id' in 'on clause'
LEFT OUTER JOIN delimail.notifications_group notificati4_ ON url2_.id=notificati4_.url_id,
delimail.emails email6_, --l 12
delimail.urls url8_ --l 13
WHERE notificati3_.email_id=email5_.id --l 14
AND notificati3_.url_id=url7_.id --l 15
AND notificati4_.email_id=email6_.id --l 16
AND notificati4_.url_id=url8_.id --l 17
AND ((notificati0_.type='EMAIL'
OR notificati0_.type='REMINDER')
AND (email1_.id IS NOT NULL)
AND email1_.user_id=?
OR notificati0_.type='URL'
AND (url2_.id IS NOT NULL)
AND url2_.user_id=?)
AND (notificati3_.id IS NOT NULL
OR notificati4_.id IS NOT NULL)
AND ((notificati3_.id IS NOT NULL)
AND notificati3_.id<?
OR (notificati4_.id IS NOT NULL)
AND notificati4_.id<?)
GROUP BY coalesce(notificati3_.id, notificati4_.id),
coalesce(notificati3_.type, notificati4_.type),
coalesce(notificati3_.email_id, notificati4_.email_id),
coalesce(notificati3_.url_id, notificati4_.url_id)
ORDER BY MAX(notificati0_.id)
And the error is:
Unknown column 'notificati0_.url_id' in 'on clause'
SQL Warning Code: 1054, SQLState: 42S22
But this query works as expected after removing marked lines 8-9, 12-13, and removing conditions in lines 14-17.
How can I convert this query to HQL? If it's possible.

I guess in this case since the query is kind of complex, You can very well go for native Query
Please see sample below:
String q="select employee_name from employee";
Query query= em.createNativeQuery(q,Object[].class);
List<Object[]> students= query.getResultList();
Please refer to the documentation below :
http://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html#createNativeQuery-java.lang.String-

Related

How to use FIND_IN_SET with select statement in symfony 5.1?

symfony version: 5.1
There is a sql statement and work in command:
SELECT
p.sn as pid,
p.title as title,
pc.title as categoryName
GROUP_CONCAT(CONCAT_WS('=', pa.`meta_key`, pa.`meta_value`) order by a.`sort_by` asc) as filters
FROM `product` as p
LEFT JOIN `product_category` as pc on pc.id = p.`category_id`
LEFT JOIN `product_model` as pm on p.`model_id` = pm.id
LEFT JOIN `brand` as b on b.id = p.brand_id
LEFT JOIN `product_attribute` as pa on pa.`product_id` = p.id
LEFT JOIN `attribute` as a on pa.`attribute_id` = a.id
WHERE p.status = 1 and a.`search_enable` = 1 and pa.`attribute_id` is not null
and FIND_IN_SET('name=test', (
SELECT
GROUP_CONCAT(CONCAT_WS('=', pa2.`meta_key`, pa2.`meta_value`))
FROM `product_attribute` as pa2
LEFT JOIN `attribute` as a2 on a2.`id` = pa2.`attribute_id`
WHERE pa2.`product_id` = p.`id` and a2.`search_enable` = 1
GROUP BY pa2.`product_id`
)) and FIND_IN_SET('age=18', (
SELECT
GROUP_CONCAT(CONCAT_WS('=', pa2.`meta_key`, pa2.`meta_value`))
FROM `product_attribute` as pa2
LEFT JOIN `attribute` as a2 on a2.`id` = pa2.`attribute_id`
WHERE pa2.`product_id` = p.`id` and a2.`search_enable` = 1
GROUP BY pa2.`product_id`
))
GROUP BY p.`id`;
But the function of FIND_IN_SET is not working in doctrine query.
$query->andWhere("FIND_IN_SET('age=18', '(SELECT GROUP_CONCAT(CONCAT_WS('=', pa2.metaKey, pa2.metaKey)) FROM ProductAttribute as pa2 LEFT JOIN Attribute as a2 on a2.id = pa2.attribute WHERE pa2.product = p.id and a2.searchEnable = 1 GROUP BY pa2.product)')");
I get error message:
PHP message: [critical] Uncaught PHP Exception Doctrine\ORM\Query\QueryException: "[Syntax Error] line 0, col 657: Error: Expected Doctrine\ORM\Query\Lexer::T_CLOSE_PARENTHESIS, got '='"
If I change the find_in_set statement remove the single quotes wit select statement:
$query->andWhere("FIND_IN_SET('age=18', (SELECT GROUP_CONCAT(CONCAT_WS('=', pa2.metaKey, pa2.metaKey)) FROM ProductAttribute as pa2 LEFT JOIN Attribute as a2 on a2.id = pa2.attribute WHERE pa2.product = p.id and a2.searchEnable = 1 GROUP BY pa2.product)");
I got this error message:
PHP message: [critical] Uncaught PHP Exception Doctrine\ORM\Query\QueryException: "[Syntax Error] line 0, col 625: Error: Expected Literal, got 'SELECT'"
How to use the FIND_IN_SET with select statement?
About the relationship of table:
1, product and product_category are manyToOne;
2, product and product_model are manyToOne;
3, product and brand are manyToOne;
4, product and product_attribute are oneToMany;
5, product_attribute and attribute are ManyToOne;
The product has many attributes that a part of it will be filtered when user search product with keywords.
So, I want to a filter function same as amazon that user can click the option of filter to get a new list of products from search result.

Error related to only_full_group_by in MySql

I have created Query Which Gives error of only_full_group_by. I Want To change Query Not SET sql_mode=only_full_group_by
#1055 - Expression #4 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'hrdk.s.item_stock_id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by#
This is the query that is giving me trouble:
SELECT `s`.`department_id`, `s`.`category_id`, `s`.`item_id`, `s`.`item_stock_id`, `s`.`tunch`, `cat`.`category_name`, `im`.`item_name`, `im`.`stock_method`, `cat`.`category_group_id`, SUM(s.grwt) AS grwt, SUM(s.ntwt) AS ntwt, sum(s.less) AS less, SUM(s.fine) AS fine
FROM `item_stock` `s`
LEFT JOIN `item_master` `im` ON `im`.`item_id` = `s`.`item_id`
LEFT JOIN `account` `pm` ON `pm`.`account_id` = `s`.`department_id`
LEFT JOIN `category` `cat` ON `cat`.`category_id` = `s`.`category_id`
WHERE (im.stock_method = 1 AND (`s`.`grwt` =0 OR `s`.`grwt` !=0)
OR (`im`.`stock_method` = 2 AND `s`.`grwt` != 0))
AND s.department_id IN(26,27,28,29,30,31,32,59)
AND `s`.`grwt` !=0
AND `s`.`department_id` = '26'
GROUP BY `s`.`category_id`, `s`.`item_id`, if(`im`.`stock_method` = 1, `s`.`tunch`, "")
ORDER BY `s`.`item_stock_id` DESC
Let me know if you need more information.
You've to add all non aggregated columns in group by
SELECT s.department_id, s.category_id, s.item_id, s.item_stock_id, s.tunch, cat.category_name, im.item_name, im.stock_method, cat.category_group_id, SUM(s.grwt) AS grwt, SUM(s.ntwt) AS ntwt, sum(s.less) AS less, SUM(s.fine) AS fine
FROM item_stock s LEFT JOIN item_master im ON im.item_id = s.item_id
LEFT JOIN account pm ON pm.account_id = s.department_id
LEFT JOIN category cat ON cat.category_id = s.category_id
WHERE (im.stock_method = 1 AND (s.grwt =0 OR s.grwt !=0) OR (im.stock_method = 2 AND s.grwt != 0))AND s.department_id IN(26,27,28,29,30,31,32,59) AND s.grwt !=0 AND s.department_id = '26'
GROUP BY s.department_id, s.category_id, s.item_id, s.item_stock_id, s.tunch, cat.category_name, im.item_name, im.stock_method, cat.category_group_id
ORDER BY s.item_stock_id DESC

Mysql sub-query return null

Hi I am a beginner I am trying to make all the result row of my subquery that is null to return 0 not null. but I am getting an error. I will really appreciate any advice. Thank you
Error Code: 1064
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 'AS 'Income'
SELECT
COUNT(DISTINCT t1.id) AS 'Val1',
COALESCE((SELECT SUM(CAST(COALESCE(r.t_payment_total,0) AS DECIMAL(18,2))) AS 'Income'
FROM reserv r
INNER JOIN newtbladds1 t ON t.t_parent_id = r.id
WHERE r.t_status!="Pending" && r.t_status!="Booked" AND r.c_mid = m.id AND t.t_type_id = t1.t_type_id
),0)AS 'Income'
FROM tbladds1 t1
JOIN tbladds1_type tt ON tt.id = t1.t_type_id
JOIN tbladdress m ON m.id = t1.t_mid
JOIN tbladdressfr mf ON mf.id = t1.t_floor_id
JOIN tblppl mp ON mp.t_mid = m.id AND mp.t_type = 'try' AND mp.t_system_id = 'ok'
GROUP BY t1.t_tool_type_id
ORDER BY m.t_m ASC, tt.t_ttype ASC, mf.t_floor ASC;
Output I removed COALESCE I am having null
Val1 Income
10 Null
2 30
23 10
5 Null
Desired Output
Val1 Income
10 0
2 30
23 10
5 0
I would suggest moving that subquery into the from clause
SELECT
t1.t_tool_type_id
, COUNT( DISTINCT t1.id ) AS `Val1`
, COALESCE(i.Income , 0 ) AS `Income`
FROM tbladds1 t1
JOIN tbladds1_type tt ON tt.id = t1.t_type_id
JOIN tbladdress m ON m.id = t1.t_mid
JOIN tbladdressfr mf ON mf.id = t1.t_floor_id
JOIN tblppl mp ON mp.t_mid = m.id
AND mp.t_type = 'try'
AND mp.t_system_id = 'ok'
left join (
SELECT
CAST( SUM(r.t_payment_total) AS decimal(18, 2) ) AS `Income`
FROM reserv r
INNER JOIN newtbladds1 t ON t.t_parent_id = r.id
WHERE r.t_status != 'Pending'
AND r.t_status != 'Booked'
AND r.c_mid = m.id
GROUP BY
t.t_type_id
) as i on t1.t_type_id = i.t_type_id
GROUP BY
t1.t_tool_type_id
;
nb: I have assumed r.t_payment_total is numeric.
I also suggest you always use single quotes for values/literals, and in MySQL backticks for identity (e.g. column headings) but really they are not essential in this query.

Unknown column where clause

I have following DQL query
SELECT
ps.id,
MAX(ps.dueDate) as due_date,
u.firstName as first_name,
u.lastName as last_name,
u.email,
IDENTITY(ps.loanApplication) as loan_application_id,
DATE_DIFF(MAX(ps.dueDate), CURRENT_DATE()) as diff
FROM
Loan\Entity\PaymentSchedule ps
LEFT JOIN
ps.paymentType pt
LEFT JOIN
ps.loanApplication la
LEFT JOIN
la.status s
LEFT JOIN
la.user u
WHERE
pt.slug != :paymentSlug AND s.keyIdentifier = :status AND diff = 14
GROUP BY
ps.loanApplication
Which translates to following SQL query
SELECT
p0_.id AS id_0,
MAX(p0_.due_date) AS sclr_1,
u1_.first_name AS first_name_2,
u1_.last_name AS last_name_3,
u1_.email AS email_4,
p0_.loan_application_id AS sclr_5,
DATEDIFF(MAX(p0_.due_date), CURRENT_DATE) AS sclr_6
FROM
payment_schedule p0_
LEFT JOIN
payment_type p2_ ON p0_.payment_type_id = p2_.id
LEFT JOIN
loan_application l3_ ON p0_.loan_application_id = l3_.id
LEFT JOIN
loan_application_status l4_ ON l3_.loan_application_status_id = l4_.id
LEFT JOIN
user u1_ ON l3_.user_id = u1_.id
WHERE
p2_.slug <> ? AND l4_.key_identifier = ? AND sclr_6 = 14
GROUP BY
p0_.loan_application_id
This gives me following error
======================================================================
PDOException
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'sclr_6' in 'where clause'
----------------------------------------------------------------------
When i replace WHERE condition
WHERE pt.slug != :paymentSlug AND s.keyIdentifier = :status AND diff = 14
With
WHERE pt.slug != :paymentSlug AND s.keyIdentifier = :status
It works perfectly and displays me correct record, i also tried following WHERE condition
WHERE pt.slug != :paymentSlug AND s.keyIdentifier = :status AND DATE_DIFF(MAX(ps.dueDate), CURRENT_DATE()) = :days_diff
WHERE pt.slug != :paymentSlug AND s.keyIdentifier = :status HAVING (DATE_DIFF(MAX(ps.dueDate), CURRENT_DATE())) = :days_diff
Above WHERE does not work as well, what am i missing here ?
Thanks.
If you want to use the alias in your WHERE clause you need a sub-select.
select *
from
(SELECT
p0_.id AS id_0,
MAX(p0_.due_date) AS sclr_1,
u1_.first_name AS first_name_2,
u1_.last_name AS last_name_3,
u1_.email AS email_4,
p0_.loan_application_id AS sclr_5,
DATEDIFF(MAX(p0_.due_date), CURRENT_DATE) AS sclr_6
FROM
payment_schedule p0_
LEFT JOIN
payment_type p2_ ON p0_.payment_type_id = p2_.id
LEFT JOIN
loan_application l3_ ON p0_.loan_application_id = l3_.id
LEFT JOIN
loan_application_status l4_ ON l3_.loan_application_status_id = l4_.id
LEFT JOIN
user u1_ ON l3_.user_id = u1_.id
) A
WHERE
slug <> ? AND key_identifier = ? AND sclr_6 = 14
This is how query is logically processed
FROM clause
WHERE clause
SELECT clause
GROUP BY clause
HAVING clause
ORDER BY clause
Since Where comes before Select you cannot use alias name in Where clause
You cannot use an alias (on the final result fields) in the WHERE clause; however, at least with MySQL, you may use a HAVING clause without needing a GROUP BY.
The expression you are using is the result of an aggregation. Replace add a having clause so the query looks like;
SELECT . . .
WHERE p2_.slug <> ? AND l4_.key_identifier = ?
GROUP BY p0_.loan_application_id
HAVING sclr_6 = 14
Note that date_diff() is not a function in MySQL. You intend datediff().

Counting rows from a big mysql query (zend)

I a developing in zend and have a rather large mysql query. The query works fine and i get the list I expect. I am doing this using Select->Where.... below is the query.
SELECT DISTINCT `d`.* FROM `deliverable` AS `d` INNER JOIN `groups` AS `g1` ON d.id = g1.deliverable_id INNER JOIN `groupmembers` AS `gm1` ON g1.id = gm1.group_id LEFT JOIN `connection` AS `c` ON d.id = c.downstreamnode_id LEFT JOIN `deliverable` AS `d1` ON c.upstreamnode_id = d1.id INNER JOIN `deliverable` AS `d2` ON CASE WHEN d1.id IS NULL THEN d.id ELSE d1.id END = d2.id INNER JOIN `groups` AS `g` ON d2.id = g.deliverable_id INNER JOIN `groupmembers` AS `gm` ON g.id = gm.group_id WHERE (g1.group_type = 100) AND (gm1.member_id = 1) AND (c.downstreamnode_id IS NULL OR d.restrict_access = 1) AND (g.group_type = 100 OR g.group_type = 110) AND (gm.member_id = 1) AND (d.deliverable_type = 110 OR d.deliverable_type = 100) GROUP BY CASE WHEN c.downstreamnode_id IS NULL THEN d.id ELSE c.downstreamnode_id END
Only problem is when I try to count the rows in a mysql query I only get 1 returned. below is the query
SELECT DISTINCT count(*) AS `rowCount` FROM `deliverable` AS `d` INNER JOIN `groups` AS `g1` ON d.id = g1.deliverable_id INNER JOIN `groupmembers` AS `gm1` ON g1.id = gm1.group_id LEFT JOIN `connection` AS `c` ON d.id = c.downstreamnode_id LEFT JOIN `deliverable` AS `d1` ON c.upstreamnode_id = d1.id INNER JOIN `deliverable` AS `d2` ON CASE WHEN d1.id IS NULL THEN d.id ELSE d1.id END = d2.id INNER JOIN `groups` AS `g` ON d2.id = g.deliverable_id INNER JOIN `groupmembers` AS `gm` ON g.id = gm.group_id WHERE (g1.group_type = 100) AND (gm1.member_id = 1) AND (c.downstreamnode_id IS NULL OR d.restrict_access = 1) AND (g.group_type = 100 OR g.group_type = 110) AND (gm.member_id = 1) AND (d.deliverable_type = 110 OR d.deliverable_type = 100) GROUP BY CASE WHEN c.downstreamnode_id IS NULL THEN d.id ELSE c.downstreamnode_id END
i generate this from by using the same 'select' that generated the first query but I reset the columns and add count in.
$this->getAdapter()->setFetchMode(Zend_Db::FETCH_ASSOC);
$select
->reset( Zend_Db_Select::COLUMNS)
->columns(array('count('.$column.') as rowCount'));
$rowCount = $this->getAdapter()->fetchOne($select);
This method works fine for all my other queries only this one i am having trouble with. I suspect it has something to do the 'CASE' I have in there but it is strange because I am getting the correct rows the the first query. Any ideas. Thanks.
FYI below are two queries that I have working successfully.
SELECT DISTINCT `po`.* FROM `post` AS `po` INNER JOIN `postinfo` AS `p` ON po.postinfo_id = p.id WHERE (p.creator_id = 1) ORDER BY `p`.`date_created` DESC
SELECT DISTINCT count(*) AS `rowCount` FROM `post` AS `po` INNER JOIN `postinfo` AS `p` ON po.postinfo_id = p.id WHERE (p.creator_id = 1) ORDER BY `p`.`date_created` DESC
In this one I have 4 rows returned in the first query and 'int 4' returned for the second one. Does anyone know why it doesnt work for the big query?
Move your DISTINCT.
SELECT COUNT(DISTINCT `po`.*) AS `rowCount` ...
Ok figured it out It was the GROUP BY that was causing only 1 result to be returned. Thanks Interrobang for you help I am sure that using DISTINCT incorrectly will have caused me a headache in the future.
Try using SQL_CALC_FOUND_ROWS in your query?
http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_found-rows
Using SQL_CALC_FOUND_ROWS is mysql-specific, but it's pretty nice for getting a full record count even when your initial query contains a limit. Once you get the count, don't include SQL_CALC_FOUND_ROWS in subsequent queries for extra records since that will cause extra load on your query.
Your initial query would be:
SELECT SQL_CALC_FOUND_ROWS DISTINCT `d`.* FROM `deliverable` AS `d` INNER JOIN `groups` ...
You'll have to do a subsequent call after your initial query executes to get the count by doing a SELECT FOUND_ROWS().
If you do a little searching, you'll find someone who extended Zend_Db_Select to include this ability.