How conversion mysql query into yii2 - yii2

Select tickets.id with calendar_date is null if last tickets.p_id(child row) calendar_date is null.
I want to convert this query in yii2 search model:
mysql query:
`SELECT b.ticket_id FROM (SELECT a.ticket_id FROM (
SELECT t.id AS ticket_id FROM tech_support.tickets t
WHERE t.tree_status_id = 2 AND t.p_id IS NULL) a
LEFT JOIN tech_support.tickets tt ON tt.p_id = a.ticket_id
WHERE tt.p_id IS NULL) b
LEFT JOIN tech_support.tickets ttt ON ttt.id = b.ticket_id WHERE
ttt.calendar_date IS NULL UNION ALL
SELECT b.maxid FROM (SELECT a.maxid, tt.calendar_date FROM (
SELECT MAX(t.id) AS maxid FROM tech_support.tickets t WHERE
t.tree_status_id = 2 GROUP BY t.p_id) a
LEFT JOIN tech_support.tickets tt ON tt.id = a.maxid) b
WHERE b.calendar_date IS NULL;`
yii2 code:
$subQuery = Tickets::find()
->select(new Expression('id as ticket_id'))
->where('tree_status_id = 2')
->andWhere('p_id is null')
->alias('a');
$subQuery->leftJoin('tickets', 'tickets.p_id = a.ticket_id')
->where('tickets.p_id is null')->all();
$query1 = (new \yii\db\Query())
->select(new Expression('id as ticket_id'))
->from($subQuery)
->where('p_id is null')
->alias('b');
$query1->leftJoin(['ttt' => 'tickets'], 'ttt.id =
b.ticket_id')
->where('ttt.calendar_date IS NULL');
$subQuery2 = Tickets::find()
->select(new Expression('MAX(tickets.id) as maxid'))
->where('tree_status_id = 2')
->groupBy(['p_id'])
->alias('a');
$subQuery2->leftJoin(['tt' => 'tickets'], 'tt.id = a.maxid')
->all();
$query2 = (new \yii\db\Query())
->select('maxid')
->from($subQuery2);
$query1->union($query2);
$query1->where('calendar_date is null');
Error Info:
Integrity constraint violation – yii\db\IntegrityException
Please help me.

Result:
//----------------query1------------------------------
$query = (new \yii\db\Query())
->select('t.id as ticket_id')
->from(['t' => 'tickets'])
->where('t.tree_status_id = 2')
->andWhere('t.p_id is null');
$subQuery = (new \yii\db\Query())
->select('a.ticket_id')
->from(['a' => $query]);
$subQuery->leftJoin(['tt' => 'tickets'], 'tt.p_id = a.ticket_id')
->where('tt.p_id is null');
$query1 = (new \yii\db\Query())
->select('b.ticket_id')
->from(['b' => $subQuery]);
$query1->leftJoin(['ttt' => 'tickets'], 'ttt.id = b.ticket_id')
->where('ttt.calendar_date IS NULL');
//----------------query2------------------------------
$subQuery2 = (new \yii\db\Query())
->select('MAX(t.id) as maxid')
->from(['t' => 'tickets'])
->where('t.tree_status_id = 2')
->groupBy(['t.p_id']);
$query2 = (new \yii\db\Query())
->select(['a.maxid', 'tt.calendar_date'])
->from(['a' => $subQuery2]);
$query2->leftJoin(['tt' => 'tickets'], 'tt.id = a.maxid');
$query3 = (new \yii\db\Query())
->select('b.maxid')
->from(['b' => $query2]);
$query3->leftJoin(['ttt' => 'tickets'], 'ttt.id = b.maxid')
->where('ttt.calendar_date IS NULL');
//----------------union queries------------------------------
$unionQuery = (new \yii\db\Query())
->from([$query1->union($query3, true)]);

Related

I need mysql query for wordpress for get ordered list

I need to get ordered list by three fields.
$sql = "
SELECT
SQL_CALC_FOUND_ROWS $wpdb->posts.ID
FROM
$wpdb->posts
INNER JOIN
$wpdb->postmeta ON ( $wpdb->posts.ID = $wpdb->postmeta.post_id )
INNER JOIN
$wpdb->postmeta AS mt1 ON ( $wpdb->posts.ID = mt1.post_id )
WHERE
1=1
AND
(
( mt1.meta_key = 'pub_series' AND mt1.meta_value = 'Book' )
OR ( mt1.meta_key = 'pub_series' AND mt1.meta_value = 'Book chapter' )
OR ( mt1.meta_key = 'pub_series' AND mt1.meta_value = 'Journal Article' )
)
/*AND
(
mt3.meta_key = 'forthcoming'
)*/
AND
$wpdb->postmeta.meta_key = 'pub_year'
AND
$wpdb->posts.post_type = 'publication'
AND
$wpdb->posts.post_status = 'publish'
GROUP BY
$wpdb->posts.ID
ORDER BY
/*FIELD(mt3.meta_key, 'forthcoming') DESC,
FIELD(mt3.meta_value, 'null') DESC,*/
//FIELD($wpdb->postmeta.meta_value,1),
$wpdb->postmeta.meta_value DESC,
$wpdb->posts.post_date DESC
";
$total = count($wpdb->get_results($sql));
$offset = ( $paged * $posts_per_page ) - $posts_per_page;
$results = $wpdb->get_results( $sql . "
LIMIT
$offset, $posts_per_page" );
This is query ordered list by two fields: [custom_field] pub_year (possible values 2018, 2017...) and [delautl wp post date field] post_date. It is ok.
But now I need to show items with [custom_field] forthcoming = 1. Problem that there three states if this field:
- items with forthcoming = 1
- items with forthcoming = 0
- and items where custom field forthcoming not exist
I need to get ordered list with firts items forthcoming = 1 and other should be ordered by pub_year and date. How I can do this. Tell me if you need some more info. Thanks a lot.
I was get needed ordered list with adding for all posts meta key forthcoming = 0 with update meta method. So all fields have this field.
Next I was used wp_query meta_query args:
$pub_series = 'Book,Book chapter,Journal Article';
$search_args = array();
if (!empty($pub_series)) {
$pub_series_arr = explode(",", $pub_series);
if (!empty($pub_series_arr)) {
$search_args_add = array(
'relation' => 'OR'
);
foreach ($pub_series_arr as $pub_series_el) {
$adv_search_query_el = trim($pub_series_el);
if (!empty($adv_search_query_el)) {
$search_args_add[] = array(
'key' => 'pub_series',
'value' => $adv_search_query_el,
'compare' => '='
);
}
}
$search_args['meta_query'][] = $search_args_add;
}
}
$search_args['meta_query'][] = array(
'relation' => 'OR',
'forthcoming_clause' => array(
'key' => 'forthcoming',
'value' => '1'
),
'forthcoming_clause0' => array(
'key' => 'forthcoming',
'value' => '0'
)
);
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
$args = array(
'post_type' => 'publication',
'post_status' => 'publish',
'posts_per_page' => 10,
'orderby' => array(
'forthcoming_clause' => 'DESC',
'meta_value' => 'DESC',
'date' => 'DESC'
),
'meta_key' => 'pub_year',
'paged' => $paged
);
$args = array_merge($args, $search_args);
$posts = new WP_Query( $args );
if ( $posts->have_posts() ) : ...

cakephp 3.4 mySQL to orm convert

my Current MYSQL query is
SELECT
cl.user_id,
COUNT(q.id) as completed_questions,
(
SELECT
SUM(points)
FROM
completed_levels
WHERE
user_id = cl.user_id
)
as level_point
FROM
completed_levels cl
JOIN
questions q
on q.level_id = cl.level_id
GROUP BY
cl.user_id;
my current ORM is following i just not able to handle select part in
$completedLevels = TableRegistry::get('CompletedLevels');
$completedLevels = $completedLevels->find('All');
$completedLevels = $completedLevels
->contain(['Users', 'Levels'])
->select([
'user_name' => 'Users.name',
'count_questions' => 'COUNT(Questions.id)',
'total_pints' => [
'select'=>'SUM(CompletedLevels.points)'
]
])
->join([
'table' => 'Questions',
'conditions' => 'Questions.level_id = CompletedLevels.level_id',
])
->group(['CompletedLevels.user_id'])
->all();
Found answer
ITS "SUB-Query"
$completedLevels = TableRegistry::get('CompletedLevels');
TableRegistry::config('cl', ['table' => 'completed_levels']);
$cl = TableRegistry::get('cl');
$cl = $cl->find('all');
$cl ->select($cl->func()->sum('points'));
$completedLevels = $completedLevels->find('All');
$completedLevels = $completedLevels
->contain(['Users', 'Levels'])
->select([
'user_name' => 'Users.name',
'count_questions' => 'COUNT(Questions.id)',
'total_pints' => $cl->where('user_id = CompletedLevels.user_id')
])->join([
'table' => 'Questions',
'conditions' => 'Questions.level_id = CompletedLevels.level_id',
])->group(['CompletedLevels.user_id']);

Yii2 - Union of two queries

Good morning Everyone,
I need a little help. I have 2 SQL queries that i need to unite. This is my first query.. (sorry if this is gonna be long)
$query1 = new Query();
$query1->params([':category' => $category, ':ownerId' => $ownerId]);
$query1->select('tmp.id, tmp.title , tmp.description, asst.thumbAssetUrl, b1.paramVal as duration, b2.paramVal as clips, asst.fileUrl as video')
->from('listdb.baseData tmp')
->innerJoin(
'listdb.tag tag',
'tag.baseDataId = tmp.id and tag.tag = :category and tag.status = "active"'
)
->innerJoin(
'listdb.baseParam b0',
'b0.baseDataId = tmp.id
and ((b0.paramName = "role"
and (b0.paramValue = "public"))
or ((select count(*) from listdb.baseParam temp
where temp.baseDataId = tmp.id and paramName = "role" )=0))
or (b0.paramName = "role" and b0.paramValue = "public" and tmp.owner = :ownerId)'
)
->leftJoin(
'listdb.baseParam b1',
'b1.baseDataId = tmp.id and b1.paramName="duration" and b1.status = "active"'
)
->leftJoin(
'listdb.baseParam b2',
'b2.baseDataId = tmp.id and b2.paramName="itemCount" and b2.status = "active"'
)
->leftJoin(
'listdb.baseParam b3',
'b3.baseDataId = tmp.id and b3.paramName="previewUrl" and b3.status = "active"'
)
->leftJoin('assetdb.baseData asst', 'asst.id = b3.paramValue and asst.status = "active"')
->where('tmp.status = "active" and tmp.application = "template" and tmp.role = "public"')
->groupBy('tmp.id')
->orderBy(['tmp.upTime' => SORT_DESC]);
and my second query is this..
$query2 = new Query();
$query2->params([':category' => $category, ':ownerId' => $ownerId]);
$query2->select('tmp.id, tmp.title , tmp.description, asst.thumbAssetUrl, b1.paramValue as duration, b2.paramValue as clips, asst.fileUrl as video')
->from('listdb.baseData tmp')
->innerJoin(
'listdb.tag tag',
'tag.baseDataId = tmp.id and tag.tag = :category and tag.status = "active"'
)
->innerJoin(
'listdb.baseParam b0',
'b0.baseDataId = tmp.id
and ((b0.paramName = "role"
and (b0.paramValue = "private" or b0.paramValue = "" and b0.paramValue != "public"))
or ((select count(*) from listdb.baseParam temp
where temp.baseDataId = tmp.id and paramName = "role" )=0))
or (b0.paramName = "role" and b0.paramValue = "public" and tmp.owner = :ownerId)'
)
->leftJoin(
'listdb.baseParam b1',
'b1.baseDataId = tmp.id and b1.paramName="duration" and b1.status = "active"'
)
->leftJoin(
'listdb.baseParam b2',
'b2.baseDataId = tmp.id and b2.paramName="item_count" and b2.status = "active"'
)
->leftJoin(
'listdb.base_parambaseParameter b3',
'b3.baseDataId = tmp.id and b3.paramName="previewUrl" and b3.status = "active"'
)
->leftJoin('assetdb.baseData asst', 'asst.id = b3.paramValue and asst.status = "active"')
->innerJoin('listdb.childRestricted cr', 'cr.baseDataId = tmp.id and cr.status = "active" and cr.owner = :ownerId')
->where('tmp.status = "active" and tmp.application = "template" and tmp.role = "private"')
->groupBy('tmp.id')
->orderBy(['tmp.upTime' => SORT_DESC]);
i tried using this union
$query = $query2->union($query1, false);
but it seems that it does not unite the two queries properly because this causes the results to double. What seems to be the problem with this. Thanks in advance.
Try this:
$unionQuery = (new \yii\db\Query())
->from(['dummy_name' => $query1->union($query2)]);
print_r($unionQuery);
More detail on Official Site

How to implement ON ( ... OR ...) mysql query in doctrine2 queryBuilder

I have a SQL query in MYSQL:
For example
SELECT s.* FROM vplanning.cities as c1
INNER JOIN vplanning.cities as c2
ON (c1.id = c2.area_id)
INNER JOIN vplanning.storages as s
ON (s.city_id = c2.id OR s.city_id = c1.id)
WHERE c1.id = 109;
In doctrine I can write something like this (from my work code):
$query = $em->getRepository('VplanningPageBundle:Storage')
->createQueryBuilder('s')
->innerJoin('s.city', 'c1')
->innerJoin('c1.area', 'c2')
->innerJoin('s.storagestype', 'st')
->where('c2.id = :cityID')
->andWhere('st.typename = :storagesTypeName')
->andWhere('s.active = :active')
->setParameters(array(
'cityID' => $cityID,
'storagesTypeName' => $storagesTypeName,
'active' => 1
))
->orderBy('s.adress')
->getQuery();
As you can see, I show my relation in
->innerJoin('s.city', 'c1')
but I need also relation like
->innerJoin('s.city', 'c2')
with this condition:
ON (s.city_id = c2.id OR s.city_id = c1.id)
But it throws this error:
Error: 'c2' is already defined
c1 and c2 are the same entity and have a inner relation.
Try this:
$repository = $em->getRepository('VplanningPageBundle:Storage');
$qb = $repository->createQueryBuilder('storage');
//We can now use the expr()
$qb->join('storage.city', 'city', Join::WITH)
->join('city.area', 'area', Join::WITH, $qb->expr()->eq('area.id', ':cityID'))
->join('storage.storagestype', 'type', Join::WITH, $qb->expr()->eq('type.typename', ':storagesTypeName'))
->where('storage.active = :active')
->setParameters(array(
'cityID' => $cityID,
'storagesTypeName' => $storagesTypeName,
'active' => 1
))
->orderBy('storage.adress');
$query = $qb->getQuery();
Try smth like this
$qb = $this->getRepository('VplanningPageBundle:City')->createQueryBuilder('c');
$qb->leftJoin('c.area', 'a')
->join('c.storage', 's', Join::ON, $qb->expr()->orX($qb->expr()->eq('c.id', 's.id'), $qb->expr()->eq('a.id', 's.id')))
->innerJoin('s.storagestype', 'st')
->where('c.id = :cityID')
->andWhere('st.typename = :storagesTypeName')
->andWhere('s.active = :active')
->setParameters(array(
'cityID' => $cityID,
'storagesTypeName' => $storagesTypeName,
'active' => 1,
))
->orderBy('s.adress')
->getQuery()
;
The solution of the problem was very difficult as for me, I have to study it :)
This is a answer for my question from some forum board:
$qb = $em->getRepository('VplanningPageBundle:Storage')->createQueryBuilder('storage');
$query = $qb->join('storage.city', 'city1', Join::WITH)
->leftJoin('city1.area', 'area', Join::WITH, $qb->expr()->eq('area.id', ':cityID'))
->leftJoin('storage.city', 'city2', Join::WITH, $qb->expr()->eq('city2.id', ':cityID'))
->join('storage.storagestype', 'type', Join::WITH, $qb->expr()->eq('type.typename', ':storagesTypeName'))
->where('storage.active = :active')
->andWhere($qb->expr()->orX($qb->expr()->isNotNull('city2'), $qb->expr()->isNotNull('area')))
->setParameters(array(
'cityID' => $cityID,
'storagesTypeName' => $storagesTypeName,
'active' => 1
))
->orderBy('storage.adress')
->getQuery();

Zend DB Union not working

I was given the task of translating an old query into Zend and all was going well until I went to create the union. I cannot post the actual contents of the query due to company regulations but basically what I have is:
$sql1 = $db->select()
->from(array('t' => 'tableOne'), array('t.id'))
->joinLeft(array('tt' => 'tableTwo'), 'tt.fk_tableOne_id = t.id', array())
->where($db->quoteInto('tt.active = ?', 'Y'));
$sql2 = $db->select()
->from(array('t' => 'tableOne'), array('t.id'))
->joinLeft(array('tt' => 'tableTwo'), 'tt.fk_tableOne_id = t.id', array())
->where($db->quoteInto('tt.active = ?', 'Y'));
$select = $db->select()->union(array($sql1, $sql2))->order('t.id');
Now, if I do a fetchAll on $sql1, it works. If I do a fetchAll on $sql2, it works. However, when I do a fetchAll on $select I get an error 1064 Syntax Error.
The sql string echoed by echo $select is basically
(ORDER BY `t.id` ASC) UNION (SELECT ... ) UNION (SELECT ...)
With the syntax error near ORDER BY ...
It seems like this should all be working since the two queries work independently, any ideas?
I tried a slightly modified query from yours:
$sql1 = $zdb->select()
->from(array('t' => 'articles'), array('t.id'))
->joinLeft(array('tt' => 'users'), 'tt.id = t.author_id', array())
->where($zdb->quoteInto('tt.level = ?', 'editor'));
$sql2 = $zdb->select()
->from(array('t' => 'blogs'), array('t.id'))
->joinLeft(array('tt' => 'users'), 'tt.id = t.updated_by', array())
->where($zdb->quoteInto('tt.level = ?', 'editor'));
$select = $zdb->select()->union(array($sql1, $sql2))->order('id');
echo $select;
and got the following:
SELECT `t`.`id` FROM `articles` AS `t` LEFT JOIN `users` AS `tt` ON tt.id = t.author_id
WHERE (tt.level = 'editor') UNION SELECT `t`.`id` FROM `blogs` AS `t` LEFT JOIN `users`
AS `tt` ON tt.id = t.updated_by WHERE (tt.level = 'editor') ORDER BY `id` ASC
What version of the framework do you have?