How can I write this in a Yii ORM findAll using CDbCriteria to fin all Users model
SELECT DISTINCT u.id, u.slug, IFNULL(MIN(m.id), 0) FROM tbl_users u
INNER JOIN tbl_status s ON (s.users_id = u.id AND s.accept > 0)
INNER JOIN tbl_message m ON (m.owner_id = s.receiver AND m.users_id = s.users_id)
WHERE u.free = 0 AND u.es_index_time <> 0 AND
u.paid = 1 AND u.withdrawed = 0 AND (
NOT EXISTS (SELECT 1 FROM tbl_users_prepay up WHERE up.users_id = u.id) OR
EXISTS (SELECT 1 FROM tbl_users_prepay up WHERE up.user_redirect_id = u.id)
)
GROUP BY u.id
LIMIT 6;
/**
* Class User - for more details:
* #see https://www.yiiframework.com/doc/api/1.1/CDbCriteria
* or
* #see http://www.bsourcecode.com/2013/06/cdbcriteria-in-yii/
*/
class User extends CActiveRecord
{
// ... user model methods
public function myCustomMethod()
{
$criteria = new CDbCriteria();
$criteria->alias = 'u';
$criteria->distinct = true;
// INNER JOIN
$criteria->join = 'INNER JOIN tbl_status s ON (s.users_id = u.id AND s.accept > 0)';
$criteria->join = 'INNER JOIN tbl_message m ON (m.owner_id = s.receiver AND m.users_id = s.users_id)';
// condition
$criteria->condition = 'u.free = 0 AND u.es_index_time <> 0 AND
u.paid = 1 AND u.withdrawed = 0 AND (
NOT EXISTS (SELECT 1 FROM tbl_users_prepay up WHERE up.users_id = u.id) OR
EXISTS (SELECT 1 FROM tbl_users_prepay up WHERE up.user_redirect_id = u.id)
)
';
$criteria->group = 'u.id';
$criteria->limit = '6';
return self::model()->findAll($criteria);
}
}
Related
I have the following code to
public function get_posted_questions($data) {
include dirname(__FILE__) . "/database.php";
$user_db_name = $dbconfig[$data['college_id']]['database'];
if (isset($data['start'])) {
$start = $data['start'];
} else {
$start = 0;
}
if (isset($data['end']) and ! empty($data['end'])) {
$end = $data['end'];
} else {
$end = 30;
}
/*
* multiple college database funda here goes
*/
$max_college_id = "
SELECT DISTINCT college_id
FROM just_ask_question
WHERE
status = '1'
AND isDeleted = '0'
AND college_id !='0'
ORDER BY id DESC
LIMIT $start, $end
";
$max_college_id_run = mysql_query($max_college_id);
$question_data = array();
$question_query = "
SELECT
Q.id,
Q.title,
Q.description,
Q.user_id,
Q.college_id,
Q.datetime,
IFNULL(GROUP_CONCAT(DISTINCT T.name),'') AS tags,
IFNULL(CONCAT_WS(' ',U.firstName,U.lastName),'') AS user_name
IFNULL(U.image,'') AS image,
IFNULL(V.id,'') AS no_of_view,
IFNULL(Vote.upvote,'') AS up_vote,
IFNULL(answer.id,0) AS no_of_answer,
IFNULL(is_upvote,0) AS upvote_status,
category_name
FROM just_ask_question AS Q
LEFT JOIN just_ask_question_tag Qt
ON Qt.question_id = Q.id
LEFT JOIN just_ask_tag T
ON T.id = Qt.tag_id
LEFT JOIN just_ask_category
ON just_ask_category.id = Q.category_id
LEFT JOIN
(
SELECT COUNT(id) as id, question_id FROM just_ask_answer
) AS answer ON answer.question_id = Q.id
";
while ( $row = mysql_fetch_assoc($max_college_id_run) ) {
$user_db_name = $dbconfig[$row['college_id']]['database'];
$question_query .= "
CASE WHEN Q.college_id = '".$row['college_id']."'
THEN LEFT JOIN $user_db_name.users U ON U.id = Q.user_id
";
}
$question_query .= "
LEFT JOIN
(
SELECT count(id) AS id, question_id FROM just_ask_view
) AS V ON V.question_id = Q.id
LEFT JOIN
(
SELECT
COUNT(upvote) as upvote,
question_id
FROM just_ask_upvote_downvote
WHERE upvote = '1' AND is_question = '1'
GROUP BY question_id
) AS Vote
ON Vote.question_id = Q.id
LEFT JOIN
(
SELECT
IF(COUNT(id) > 0,1,0) AS is_upvote,
question_id
FROM just_ask_upvote_downvote
WHERE
upvote = '1'
AND college_id = '" . $data['college_id'] . "'
AND user_id = '" . $data['user_id'] . "'
AND is_question = '1'
) AS Is_Vote
ON Is_Vote.question_id = Q.id
WHERE
Q.status = '1'
AND Q.isDeleted = '0'
AND CASE
WHEN Q.visibility = 0 AND Q.college_id != 0 THEN Q.college_id = '" . $data['college_id'] . "'
ELSE true
END
";
if (!empty($data['search_text'])) {
$search_text = $data['search_text'];
$question_query .= " and (Q.title like '%$search_text%' or Q.description like '%$search_text%' or T.name like '%$search_text%')";
}
$question_query .= " group by Q.id order by Q.id desc limit $start,$end";
$question_query_run = mysql_query($question_query);
/* get weather question exist */
$check_num_rows = mysql_num_rows($question_query_run);
if ($check_num_rows > 0) {
while ($row = mysql_fetch_assoc($question_query_run)) {
if ($row['image'] != '') {
$row['thumbnail'] = USER_THUMBNAIL_URL . $row['image'];
$row['image'] = IMAGE_URL . $row['image'];
} else
$row['thumbnail'] = '';
$question_data[] = $row;
}
$status['statuscode'] = "1";
$status['statusmessage'] = "ok";
$status['question_data'] = $question_data;
$response['response'] = $status;
echo json_encode($response);
die();
}else {
$status['statuscode'] = "2";
$status['statusmessage'] = "There is no record found";
$response['response'] = $status;
echo json_encode($response);
die();
}
}
AND the db config file like which contain the database name information
like
$dbconfig['1'] = array(
'host' => 'localhost',
'user_name' => 'root',
'password' => 'test123*',
'database' => 'staging_myuniversity'
);
$dbconfig['2'] = array(
'host' => 'localhost',
'user_name' => 'root',
'password' => 'test123*',
'database' => 'staging_myuniversity_dias'
);
the database are reside on same server and with full permission.
the query generate like this
select Q.id,Q.title,Q.description,Q.user_id,Q.college_id,
Q.datetime,
ifnull(group_concat(distinct T.name),'') as tags,
ifnull(CONCAT_WS(' ',
U.firstName,U.lastName),'') as user_name,
ifnull(U.image,
'') as image,ifnull(V.id,'') as no_of_view,
ifnull(Vote.upvote,
'') as up_vote,
ifnull(answer.id,0) as no_of_answer,
ifnull(is_upvote,
0
) as upvote_status,
category_name
from just_ask_question as Q
left join just_ask_question_tag Qt on Qt.question_id = Q.id
left join just_ask_tag T on T.id = Qt.tag_id
left join just_ask_category on just_ask_category.id = Q.category_id
left join
( SELECT count(id) as id,question_id
from just_ask_answer
) as answer on answer.question_id = Q.id case when Q.college_id = '1' then
left join staging_myuniversity.users U on U.id = Q.user_id case when Q.college_id = '12'then
left join campify_solutions_mathura.users U on U.id = Q.user_id case when Q.college_id = '4' then
left join staging_myuniversity_nit_kkr.users U on U.id = Q.user_id case when Q.college_id = '2' then
left join staging_myuniversity_dias.users U on U.id = Q.user_id
left join
( SELECT count(id) as id,question_id
from just_ask_view
) as V on V.question_id = Q.id
left join
( SELECT count(upvote) as upvote,question_id
from just_ask_upvote_downvote
where upvote = '1'
and is_question = '1'
group by question_id
) as Vote on Vote.question_id = Q.id
left join
( SELECT if(count(id) > 0,1,0) as is_upvote,question_id
from just_ask_upvote_downvote
where upvote = '1'
and college_id = '1'
and user_id = '1'
and is_question = '1'
) as Is_Vote on Is_Vote.question_id = Q.id
where Q.status = '1'
and Q.isDeleted = '0'
and case when Q.visibility = 0
and Q.college_id != 0 then Q.college_id = '1' else true end
group by Q.id
order by Q.id desc
limit 0,30
I need to make the join on different databases based on college id
first i fetch the distinct college id from the question then make a loop
for college id and try to make join condition but i am getting error there is any suggestion and help
I won't help you with entire query (I'll just list some concerns), but this "case-join" might be solved with UNION ALL subquery this way:
INNER JOIN (
SELECT 1 AS college_id, id, firstName, lastName, image
FROM staging_myuniversity.users
UNION ALL
SELECT 12 AS college_id, id, firstName, lastName, image
FROM campify_solutions_mathura.users
UNION ALL
...
) AS U ON U.college_id = Q.college_id AND U.id = Q.user_id
When you join counters with subqueries like SELECT count(), some_id use GROUP_BY some_id as well. Otherwise you'll count all rows in table and join this result for one (first/random) id only (if it passes without error).
It looks like You use LEFT JOIN too much. It means attach to the result on left regardless if any row on the right matches (joins null columns then). It's slow, gives large data sets and results with nulls for most of these columns seems useless.
Join subquery with GROUP BY clause to get concatenated tags
If large portion of this data will be repeated across the rows (see: N+1 problem) splitting queries (and merging subsets to common "header") might be a good idea.
Build your query one step at a time. Test subqueries if you're not sure of its results. Start with resource consuming parts - it might get slow at some point and you'll end up splitting it anyway.
... case when Q.college_id = '1' then left join ...
does not make sense. What are you trying to do?
Performance tip: Don't use LEFT JOIN ( SELECT ... ) Instead of that and IFNULL(...), simply do
SELECT ...,
IFNULL(( SELECT ... ), '') AS upvotes,
As for pivoting, I must say simply, and strongly, that some tasks are better left to your application code, not SQL.
I am having trouble finishing my MySQL JOIN. I am unsure of the syntax for the last part of my query.
My Query:
$posts_query= "
SELECT *
FROM posts p
JOIN relations r ON p.user_id = r.recipient
WHERE (r.status = 1 OR r.status = 2)
AND (r.sender = '".$user_id."' OR p.user_id = '".$user_id."')
// How do I write this part?
AND skip where r.status = 1 and p.privacy = 2 where p.user_id != $user_id //
ORDER BY p.post_id DESC;
";
Instead of 'skip', just set it so that the value isn't true, using NOT:
SELECT *
FROM posts p
JOIN relations r ON p.user_id = r.recipient
WHERE (r.status = 1 OR r.status = 2)
AND (r.sender = '$user_id' OR p.user_id = '$user_id')
AND NOT (r.status = 1 AND p.privacy = 2 AND p.user_id != '$user_id')
ORDER BY p.post_id DESC;"
SELECT *
FROM posts p
JOIN relations r ON p.user_id = r.recipient
WHERE r.status in (1,2)
AND (r.sender = '$user_id' OR p.user_id = '$user_id')
AND NOT ( r.status = 1 and p.privacy = 2 AND p.user_id != '$user_id' )
ORDER BY p.post_id DESC;
I have a PHP script that loops through 2000+- records uisng a while loop. Within this while loop a postgres sql query has to be performed, unfortunately it can't be excluded from the while loop.
$sql = "(SELECT (timestamp) AS time FROM followups as f
JOIN campaigns as c ON c.id = f.campid
WHERE c.clientid = ".trim($clientid)." AND c.contractno = '".trim($c)."' AND (LOWER(person) IN (SELECT LOWER(userid) FROM users WHERE type IN('S','X')) OR LOWER(person) IN (SELECT LOWER(name) FROM users WHERE type IN('S','X'))) )
UNION ALL (SELECT (timestamp) AS time FROM followups as f WHERE (contractno ='".trim($c)."'
OR contractno LIKE '%".trim($c)."||".trim($clientid)."%'
OR contractno = '".trim($c)."||".trim($clientid)."') AND (LOWER(person) IN (SELECT LOWER(userid) FROM users WHERE type IN('S','X')) OR LOWER(person) IN (SELECT LOWER(name) FROM users WHERE type IN('S','X'))) )
UNION ALL (select (f.timestamp) AS time FROM followups as f
JOIN campaigns as c on c.id = f.campid WHERE c.clientid = ".trim($clientid)."
AND c.clientid in (
SELECT id FROM easy_mapping where id = ".trim($clientid).") AND (LOWER(person) IN (SELECT LOWER(userid)
FROM users WHERE type IN('S','X')) OR LOWER(person) IN
(SELECT LOWER(name) FROM users WHERE type IN('S','X'))))";
$result = pg_query($conn,$sql);
The query above is included in the while loop, the first few records perform very quickly and then the script starts to slow down, taking almost a day to complete the script. Is there a way to write the exact query above differently to gain the same results?
UPDATE:
Here's the complete loop
$dates = array();
$clientid = str_replace("\t", '', $clientid);
foreach ($contracts as $c) {
$c = str_replace("\t", '', $c);
$sql = "(SELECT MAX(timestamp) AS time FROM followups as f
JOIN campaigns as c ON c.id = f.campid
WHERE c.clientid = ".trim($clientid)." AND c.contractno = '".trim($c)."' AND (LOWER(person) IN (SELECT LOWER(userid) FROM users WHERE type IN('S','X')) OR LOWER(person) IN (SELECT LOWER(name) FROM users WHERE type IN('S','X'))) )
UNION ALL (SELECT MAX(timestamp) AS time FROM followups as f WHERE (contractno ='".trim($c)."'
OR contractno LIKE '%".trim($c)."||".trim($clientid)."%'
OR contractno = '".trim($c)."||".trim($clientid)."') AND (LOWER(person) IN (SELECT LOWER(userid) FROM users WHERE type IN('S','X')) OR LOWER(person) IN (SELECT LOWER(name) FROM users WHERE type IN('S','X'))) )
UNION ALL (select MAX(f.timestamp) AS time FROM followups as f
JOIN campaigns as c on c.id = f.campid WHERE c.clientid = ".trim($clientid)."
AND c.clientid in ( SELECT id FROM easy_mapping where id = ".trim($clientid).") AND (LOWER(person) IN (SELECT LOWER(userid) FROM users WHERE type IN('S','X')) OR LOWER(person) IN (SELECT LOWER(name) FROM users WHERE type IN('S','X'))))";
$result = pg_query($conn,$sql);
if (pg_num_rows($result)>0) {
while ($row = pg_fetch_array($result, null, PGSQL_ASSOC)) {
if (empty($row['time'])) {
continue;
}
$dates[] = $row['time'];
}
}
pg_free_result($result);
}
if (empty($dates)) {
return false;
} else {
$max = max($dates);
if (strtotime(date("Y-m-d")) < strtotime(date("Y-m-t"))) {
$compdate = date("Y-m-01", strtotime("-1 month") );
} else {
$compdate = date("Y-m-01");
}
if (strtotime($compdate) > $max) {
return false;
} else {
return true;
}
}
unset($dates);
The following is the result of what I can understand from your really junkish code.
$clientid = trim(str_replace("\t", '', $clientid));
$sql = "
select max(time)
from (
(
select max(timestamp) as time
from
followups f
inner join
campaigns c on c.id = f.campid
inner join
users u on lower(f.person) in (lower(u.userid), lower(u.name))
where
c.clientid = $clientid
and u.type in('S','X')
)
union
(
select max(timestamp) as time
from
followups as f
inner join
users u on lower(f.person) in (lower(u.userid), lower(u.name))
where
contractno like ('%' || $clientid || '%')
and u.type in('S','X')
)
union
(
select max(f.timestamp) as time
from
followups as f
join
campaigns as c on c.id = f.campid
inner join
users u on lower(f.person) in (lower(u.userid), lower(u.name))
inner join
easy_mapping em on c.clientid = em.id
where
c.clientid = $clientid
and u.type in('S','X')
)) s
";
$result = pg_query($conn,$sql);
if (pg_num_rows($result) == 0) {
return false;
} else {
$max = $row['time'];
if (strtotime(date("Y-m-d")) < strtotime(date("Y-m-t"))) {
$compdate = date("Y-m-01", strtotime("-1 month") );
} else {
$compdate = date("Y-m-01");
}
if (strtotime($compdate) > $max) {
return false;
} else {
return true;
}
}
pg_free_result($result);
I have the following query that I would like to convert to use doctrine's query builder.
SELECT
u.user_id,
u.username,
u.create_date AS join_date,
u.last_login_date,
u.membership_level,
u.create_date,
avg(round((ug.toggle_count / ceil((g.ply_count + 1) / 2)) * 100, 1)) AS __avg_toggle_ratio,
count(g.game_id) AS __game_count,
ugse.rating AS __echess_rating,
ugse.total_win_count AS __echess_win_count,
ugse.total_loss_count AS __echess_loss_count,
ugse.total_draw_count AS __echess_draw_count,
(SELECT concat(ugsl.rating,'|',ugsl.total_win_count,'|',ugsl.total_loss_count,'|',ugsl.total_draw_count) FROM user_game_stats_live ugsl WHERE ugsl.user_id = u.user_id AND ugsl.game_time_class = 'lightning') AS __lightning_data,
(SELECT concat(ugsl.rating,'|',ugsl.total_win_count,'|',ugsl.total_loss_count,'|',ugsl.total_draw_count) FROM user_game_stats_live ugsl WHERE ugsl.user_id = u.user_id AND ugsl.game_time_class = 'blitz') AS __blitz_data,
(SELECT concat(ugsl.rating,'|',ugsl.total_win_count,'|',ugsl.total_loss_count,'|',ugsl.total_draw_count) FROM user_game_stats_live ugsl WHERE ugsl.user_id = u.user_id AND ugsl.game_time_class = 'standard') AS __standard_data,
(SELECT uts.rating FROM user_tactics_settings uts WHERE uts.user_id = u.user_id AND uts.attempt_count >= 10) AS __tactics_rating
FROM
game g
JOIN user_game ug ON g.game_id = ug.game_id
JOIN user_game_stats_email ugse ON ug.user_id = ugse.user_id
JOIN user u ON ug.user_id = u.user_id
WHERE
g.last_move_time >= DATE_SUB(NOW(), INTERVAL 5 DAY) AND
g.ply_count >= 20 AND
u.is_enabled = 1
GROUP BY
ug.user_id
HAVING
__avg_toggle_ratio >= 90 AND
__game_count >= 10
ORDER BY
__avg_toggle_ratio DESC
Is the query builder capable of rewriting this kind of query? Should I use other methods instead, if so, how?
I'm not sure about query builder, but I woyld use the 'createNativeQuery' method:
<?php
use Doctrine\ORM\Query\ResultSetMapping;
$rsm = new ResultSetMapping();
// build rsm here
$query = $entityManager->createNativeQuery("SELECT
u.user_id,
u.username,
u.create_date AS join_date,
u.last_login_date,
u.membership_level,
u.create_date,
avg(round((ug.toggle_count / ceil((g.ply_count + 1) / 2)) * 100, 1)) AS __avg_toggle_ratio,
count(g.game_id) AS __game_count,
ugse.rating AS __echess_rating,
ugse.total_win_count AS __echess_win_count,
ugse.total_loss_count AS __echess_loss_count,
ugse.total_draw_count AS __echess_draw_count,
(SELECT concat(ugsl.rating,'|',ugsl.total_win_count,'|',ugsl.total_loss_count,'|',ugsl.total_draw_count) FROM user_game_stats_live ugsl WHERE ugsl.user_id = u.user_id AND ugsl.game_time_class = 'lightning') AS __lightning_data,
(SELECT concat(ugsl.rating,'|',ugsl.total_win_count,'|',ugsl.total_loss_count,'|',ugsl.total_draw_count) FROM user_game_stats_live ugsl WHERE ugsl.user_id = u.user_id AND ugsl.game_time_class = 'blitz') AS __blitz_data,
(SELECT concat(ugsl.rating,'|',ugsl.total_win_count,'|',ugsl.total_loss_count,'|',ugsl.total_draw_count) FROM user_game_stats_live ugsl WHERE ugsl.user_id = u.user_id AND ugsl.game_time_class = 'standard') AS __standard_data,
(SELECT uts.rating FROM user_tactics_settings uts WHERE uts.user_id = u.user_id AND uts.attempt_count >= 10) AS __tactics_rating
FROM game g
JOIN user_game ug ON g.game_id = ug.game_id
JOIN user_game_stats_email ugse ON ug.user_id = ugse.user_id
JOIN user u ON ug.user_id = u.user_id
WHERE g.last_move_time >= DATE_SUB(NOW(), INTERVAL 5 DAY)
AND g.ply_count >= 20
AND u.is_enabled = 1
GROUP BY ug.user_id
HAVING __avg_toggle_ratio >= 90
AND __game_count >= 10
ORDER BY __avg_toggle_ratio DESC', $rsm);
$query->setParameter(1, 'romanb');
$data = $query->getResult();
So i'm filling in for our developer at the moment (be for-warned i'm a beginner) but I"m trying to simply sort my search results by profiles that have a profile picture included (i.e, i don't want blank profile pictures to show up at the top of the results...they should all be at the end of the results)...Note that there are a couple user types which is why there is so much code...
I'm pretty sure where i'm going wrong is the 2 lines...
ORDER BY $order u.picture ISNULL DESC"; (which relates to ordering by profile pictures). Would really appreciate any and all help...thx!
The code is as follows:
if ($user_type == 1) {
$sql = "SELECT a.*, u.*,
(SELECT COUNT(DISTINCT userId) FROM LF_usertype_A WHERE usertype_BId = u.userId AND status = 1) as i_cnt,
(SELECT COUNT(productId) FROM LF_products WHERE userId = u.userId AND status = 1) as product_cnt,
(SELECT COUNT(transactionId)
FROM LF_Transactions
WHERE usertypeBId = u.userId
AND (status = 1 OR status = 2)
AND type = 9
AND userId != usertypeBId
AND userId != usertypeAId) AS cnt
FROM LF_Users u
JOIN LF_products a ON a.userId = u.userId
LEFT JOIN LF_Transactions t ON t.productId = a.productId
WHERE a.status = 1
AND u.status = 1
AND u.userType = :ut $where
GROUP BY u.userID
ORDER BY $order u.name DESC LIMIT 200";
} elseif ($filter != "recent" && $user_type == 2) {
$sql = "SELECT u.*,
(SELECT COUNT(a.productId) FROM LF_usertypeA a INNER JOIN LF_products ON a.productId = m.productId INNER JOIN LF_Users uu ON uu.userId = a.usertypeAId WHERE a.userId = u.userId AND uu.status = 1 AND a.status = 1 AND m.status = 1) as product_cnt,
(SELECT COUNT(transactionId)
FROM LF_Transactions
WHERE usertypeBId = u.userId
AND (status = 1 OR status = 2)
AND type = 9
AND userId != usertypeAId
AND userId != usertypeBId) AS cnt
FROM LF_Users u
LEFT JOIN LF_Transactions t ON t.usertypeBId = u.userId
WHERE u.status = 1
AND u.userId != 1
AND u.userType = :ut $where
GROUP BY u.userID
ORDER BY $order u.name DESC LIMIT 200
ORDER BY $order u.picture ISNULL DESC";
} else {
$sql = "SELECT u.*,
(SELECT COUNT(a.productId) FROM LF_usertype_A a INNER JOIN LF_products m ON a.productId = m.productId INNER JOIN LF_Users uu ON uu.userId = a.usertypeAId WHERE a.userId = u.userId AND uu.status = 1 AND a.status = 1 AND m.status = 1) as product_cnt,
(SELECT COUNT(transactionId)
FROM LF_Transactions
WHERE usertypeBId = u.userId
AND (status = 1 OR status = 2)
AND type = 9
AND userId != usertypeAId
AND userId != usertypeBId) AS cnt
FROM LF_Users u
WHERE u.status = 1
AND u.userId != 1
AND u.userType = :ut $where
GROUP BY u.userID
ORDER BY $order u.name DESC LIMIT 200
ORDER BY $order u.picture ISNULL DESC";
}
You would have to put the isnull condition before your regular sort order if you want it to take precedence:
ORDER BY ISNULL(u.picture), $order