I have problem with custom ordering of result in Native Query Doctrine 2. I have this SQL tested on server:
SELECT
c.id, c.is_verified, c.email, c.phone, i.id as identityId,
i.firstname, i.lastname, g.id as groupId, g.name as groupName,
r.id as roleId, r.name as roleName
FROM
UserCredential c
JOIN
UserIdentity i
ON
i.id = c.identity_id
JOIN
Role r
ON
r.id = c.role_id
LEFT JOIN
`Group` g
ON
g.id = c.group_id
ORDER BY
i.firstname ASC
LIMIT
10
OFFSET
0
Everything works but, when I rewrote this to Native Query in Custom repository:
$query = $this->_em->createNativeQuery('
SELECT
c.id,
c.is_verified,
c.email,
c.phone,
i.id as identityId,
i.firstname,
i.lastname,
g.id as groupId,
g.name as groupName,
r.id as roleId,
r.name as roleName
FROM
UserCredential c
JOIN
UserIdentity i
ON
i.id = c.identity_id
JOIN
Role r
ON
r.id = c.role_id
LEFT JOIN
`Group` g
ON
g.id = c.group_id
ORDER BY
:orderBy
LIMIT
:lmt
OFFSET
:ofs
', $rsm);
$query->setParameter('orderBy', implode(', ', $orderBy));
$query->setParameter('lmt', $limit);
$query->setParameter('ofs', $offset);
Where $orderBy is array $column => $orderType.
But if I change order by parameters result from this query is always returned with default ordering (c.id ASC).
I've tested this and query is generated OK but I don't know why is result always ordered by default. Is Doctrine 2 somehow ignoring ORDER BY?
Related
Here is my SQL query which joins 4 tables and it works correctly.
SELECT pl.lms_id, u.id, REPLACE(trim(u.`url`), 'www.', '') AS url, trim(u.`name`) as name, p.date_removed, p.status, p.ignore_status FROM `adl_seo_status` p INNER JOIN `adl_user_profiles` u on p.profile_id = u.id INNER JOIN adl_tw_profile_acc_type ac on p.profile_id = ac.profile_id LEFT JOIN `adl_lms_prof_list` pl on u.id = pl.profile_id WHERE u.`vpg_id`='2' AND u.`status` = 'Y' and ac.acc_type_id = '2' ORDER BY u.`url` ASC, p.id DESC
I am facing an issue that, the table adl_seo_status has multiple entries for a single profile_id. So, that accounts are repeating in my listing. I want that account as a single row which means the distinct value of accounts based on profile_id.
You need to use group by, for example:
SELECT
pl.lms_id,
u.id,
REPLACE(trim(u.`url`), 'www.', '') AS url,
trim(u.`name`) AS name,
p.date_removed,
p.status,
p.ignore_status
FROM `adl_seo_status` p INNER JOIN `adl_user_profiles` u ON p.profile_id = u.id
INNER JOIN adl_tw_profile_acc_type ac ON p.profile_id = ac.profile_id
LEFT JOIN `adl_lms_prof_list` pl ON u.id = pl.profile_id
WHERE u.`vpg_id` = '2' AND u.`status` = 'Y' AND ac.acc_type_id = '2'
ORDER BY u.`url` ASC, p.id DESC GROUP BY p.profile_id;
I am applying Left Join with Sub query & where clause
It seems fine no syntax error but the columns I am selecting from that sub query always returns me Null. I have executed the same part in my SQL section, it gives me record. Kindly have a look on the query and let me know if any thing is possible or if question is not clear.
SELECT alt.userId, u.name, t.name AS teamName, alt.startDateTime, v.name AS villageName, c.name AS clusterName, startLat, startLong, latlng.lat, latlng.long
FROM activity_log_tim AS alt
JOIN user AS u ON u.userId = alt.userId
JOIN team_members AS tm ON tm.memberId = u.userId
JOIN team AS t ON t.teamId = tm.teamId
JOIN village AS v ON v.villageId = alt.villageId
JOIN cluster_villages AS cv ON cv.villageId = v.villageId
JOIN cluster AS c ON c.clusterId = cv.clusterId
LEFT JOIN (SELECT lat, long,dateTime, scheduleId FROM activity_log_gps LIMIT 1) AS latlng ON latlng.scheduleId = alt.scheduleId
WHERE DATE(alt.startDateTime) = '2015-09-05' AND DATE(alt.endDateTime) = '0000-00-00' GROUP BY alt.userId ORDER BY latlng.dateTime DESC
Well it's supposed to since you are performing a LEFT JOIN which produces NULL if no match occurs. So either you can perform a INNER JOIN or use a COALESCE function like below
SELECT alt.userId, u.name,
t.name AS teamName,
alt.startDateTime,
v.name AS
villageName,
c.name AS clusterName,
startLat,
startLong,
COALESCE(latlng.lat, 23), //Notice the use of COALESCE. If null will return 23 as default
COALESCE(latlng.long, 32)
I have the following JOIN query already done:
$stmt = $cxn->prepare('SELECT p.post_id, p.reply_to, p.parent_id, p.post_path, p.user_id, p.content, p.datetime, p.total_likes, p.total_replies, p.total_reposts, u.username, u.display_name FROM posts p LEFT JOIN users u ON p.user_id = u.user_id WHERE p.user_id IN (SELECT following_id FROM follows WHERE user_id = ?) AND p.removed != 1 ORDER BY p.datetime DESC LIMIT 26');
$stmt->bind_param('i', $user_info[0]);
$stmt->execute();
I have another query that's only purpose is to check if a row exists or not:
$stmt = $cxn->prepare('SELECT COUNT(like_id) FROM likes WHERE post_id = ? AND user_id = ?');
$stmt->bind_param('ii', $row['post_id'], $user_info[0]); // $row['post_id'] is the value of p.post_id from the first query
$stmt->execute();
How would I join the second query into the first one? I've never joined 3 tables so I'm unsure of the procedure.
Thanks.
Joining three tables in a query is like joining two, except... you join three.
Basically it would go something like this:
SELECT p.post_id (...), u.username (...), COUNT(l.like_id) AS nbOfLikes
FROM posts p
LEFT JOIN users u ON p.user_id = u.user_id
LEFT JOIN likes l ON l.post_id = p.post_id AND l.user_id = u.user_id
WHERE p.user_id IN
(SELECT following_id
FROM follows
WHERE user_id = ?)
AND p.removed != 1
ORDER BY p.datetime DESC
LIMIT 26;
-- Actually I think a UNION would perhaps be more adapted to your need concerning the likes table.
If you always have the user_id filled into your table posts and it's a foreign key, avoid to use a left join statement, you can get a better performance using join statement. To join 3 or more tables you can just add the join statement:
SELECT
p.post_id
, p.reply_to
, p.parent_id
, p.post_path
, p.user_id
, p.content
, p.datetime
, p.total_likes
, p.total_replies
, p.total_reposts
, u.username
, u.display_name
FROM posts p
JOIN users u ON p.user_id = u.user_id WHERE p.user_id IN (SELECT following_id FROM follows
JOIN TABLE_2 ON TABLE_2.id = posts.TABLE_id
JOIN TABLE_3 ON TABLE_3.id = posts.TABLE_id
...
WHERE
user_id = ?)
AND p.removed != 1
ORDER BY p.datetime DESC
LIMIT 26
i want to use JOIN categories c ON c.id = i.category if post_type is 1 and i want to have c.title AS category_name, in SELECT otherwise JOIN categories c ON c.id = i.category and c.title AS category_name, must be not worked in query , i'm using case for join but my sql command is not correct. please help me. in all description my quastion means is how to change this below command to if post_type is 1 join must be not work
SELECT SQL_CALC_FOUND_ROWS
i. * ,
c.title AS category_name,
s.title AS status_title,
i.thumb_image,
CONCAT( u.name, ' ', u.family ) AS author
FROM contents i
LEFT JOIN categories c
ON i.category = CASE post_type WHEN 1 then c.id END
JOIN users u ON u.id = i.posted_by
JOIN status_topics s ON s.id = i.t_status
WHERE i.id = 2
I would always do the LEFT JOIN and put a condition on the column itself:
SELECT SQL_CALC_FOUND_ROWS
i. * ,
IF(i.post_type = 1, c.title, NULL) AS category_name,
s.title AS status_title,
i.thumb_image,
CONCAT( u.name, ' ', u.family ) AS author
FROM contents i
LEFT JOIN categories c ON i.category = c.id
JOIN users u ON u.id = i.posted_by
JOIN status_topics s ON s.id = i.t_status
WHERE i.id = 2
Hello can anybody see why this query fails?
SELECT A.idAd, A.ads_in_Cat, A.title, A.currency, A.price,
A.in_dpt, A.description, A.featured FROM ads A
LEFT JOIN featured F ON F.ad = A.idAd
INNER JOIN dept D ON D.id_dept = A.in_dpt
INNER JOIN sub_cat_ad S ON S.id_sub_cat = A.ads_in_Cat
INNER JOIN cat_ad C ON C.idCat_ad = S.from_cat_ad
ORDER BY A.featured DESC LIMIT :limit, :offset
But this one works:
SELECT *FROM ads
LEFT JOIN featured ON featured.ad = ads.idAd
INNER JOIN dept ON dept.id_dept = ads.in_dpt
INNER JOIN sub_cat_ad ON id_sub_cat = ads.ads_in_Cat
INNER JOIN cat_ad ON idCat_ad = sub_cat_ad.from_cat_ad
ORDER BY featured DESC LIMIT :limit, :offset
In the first one, I don't want all columns from the table "ads", the query returns only columns till ...FROM ads A.
If you specify to only select fields from A that's what you get: Only fields from A.
If you want fields from other tables too you have to specify them as well.
SELECT
A.idAd, A.ads_in_Cat, A.title, A.currency, A.price, A.in_dpt, A.description, A.featured,
F.*,
D.*,
S.*,
C.*
FROM ads A
LEFT JOIN featured F ON F.ad = A.idAd
INNER JOIN dept D ON D.id_dept = A.in_dpt
INNER JOIN sub_cat_ad S ON S.id_sub_cat = A.ads_in_Cat
INNER JOIN cat_ad C ON C.idCat_ad = S.from_cat_ad
ORDER BY A.featured DESC LIMIT :limit, :offset