Any one have a example how to order before group with leftjoin in zend paginator adapter ?
new Zend_Paginator_Adapter_DbSelect($this->db->select()
->from(array( 'a' => $this->prefix.'contest' ), array('id'))
->joinLeft(array( 'b' => $this->prefix.'logo_to_contest'),'a.id=b.contest_id', array('img'))
->group('a.id')
->order('a.end','a.date_start DESC','b.id RAND()')
)
From mysql manuel
In general, clauses used must be given in exactly the order shown in
the syntax description. For example, a HAVING clause must come after
any GROUP BY clause and before any ORDER BY clause. The exception is
that the INTO clause can appear either as shown in the syntax
description or immediately following the select_expr list.
and in the syntax description group comes before order so it has nothing to do with zend
it's mysql that requires that you put group before order.
However to get around this issue and group after ordering you can select with a subquery with order then group on a new select like :
$subselect = $db->select()
->from(array( 'a' => $this->prefix.'contest' ), array('id'))
->joinLeft(array( 'b' => $this->prefix.'logo_to_contest'),'a.id=b.contest_id', array())
->order('a.end','a.date_start DESC','b.id RAND()');
$select = $db->select()->from(a(array( 'a' => $this->prefix.'contest' ), array('id'))
->joinLeft(array( 'b' => $this->prefix.'logo_to_contest'),'a.id=b.contest_id', array('img'))
->where("a.id in ($subselect)")
->group('a.id');
Related
Below is my sql code which is working properly
SELECT oid, date(ordered_on) AS ord, count(date(ordered_on)) AS cnt
FROM order
GROUP BY ord DESC
LIMIT 10
But when i apply it in laravel, I am not able to evaluate the result. Below is the laravel code
DB::table('order')
->select(DB::raw('oid, date(ordered_on) as ord, count(date(ordered_on)) as cnt'))
->groupBy('ord')
->orderBy('oid', 'desc')
->limit(10)
->get();
Your raw MySQL query should ideally not be working, because it doesn't make much sense. I sense that what you want to do is get a count of records by date. If so, then you want this query:
SELECT DATE(ordered_on), COUNT(*) AS cnt
FROM `order`
GROUP BY DATE(ordered_on);
This would imply the following Laravel code:
DB::table('order')
->select(DB::raw('DATE(ordered_on) AS ord, COUNT(*) AS cnt'))
->groupBy('ord')
->orderBy('ord', 'desc')
->limit(10)
->get();
By the way, don't name your tables, columns, etc. using reserved MySQL keywords like order. I needed to escape order in my query, and you will need to do the same, perpetually, moving forward.
You are using strict mode in laravel. By the you can tweak it to your needs.
got to config/database.php in set strict=>false and you are good to go.
'mysql' => [
// ....
'strict' => false
],
I want to create a SQL(MySQL) query in Zend Framework 2 like:
SELECT a.id,
a.name,
a.age,
(SELECT MAX(score)
FROM scores AS s
WHERE s.user_id = a.id) AS max_score,
(SELECT SUM(time)
FROM games_played_time AS gpt
WHERE gpt.user_id = a.id) AS time_played
FROM users AS a
ORDER BY last_visited DESC
LIMIT 0, 100
Mind that this is an artificial example of existing query.
I tried creating sub-queries and then creating main select query where when I use:
$select->columns(
array(
'id',
'name',
'age',
'max_score' => new Expression('?', array($sub1),
'time_played' => new Expression('?', array($sub2)
)
I also tried using:
$subquery = new \Zend\Db\Sql\Expression("({$sub->getSqlString()})")
And even lambda functions like suggested here: http://circlical.com/blog/2014/1/27/zend-framework-2-subqueries-subselect-and-table-gateway
Still no luck because all the time I keep getting errors like:
No data supplied for parameters in prepared statement
And when I succeed in making the query work, it ends up that column contains the text of sub-queries. It starts to look that it is not possible to make multiple expressions in columns method. Any ideas?
SOLVED:
I rewrote query by query as #Tim Klever proposed. Everythin worked except one query. It turns out there is some kind of issue when using limit in subquery and in main query. In my case one of the subqueries returns multiple rows, so I ussed limit(1) to force return of a single value. But using that turned out to produce error:
No data supplied for parameters in prepared statement
I changed the query to use MAX instead of limit and now it works. Later will try to debug why this is happening.. Thank you!
The following worked for me to produce the query you listed
$maxScoreSelect = new Select();
$maxScoreSelect->from(array('s' => 'scores'));
$maxScoreSelect->columns(array(new Expression('MAX(score)')));
$maxScoreSelect->where->addPredicates('s.user_id = a.id');
$sumTimeSelect = new Select();
$sumTimeSelect->from(array('gpt' => 'games_played_time'));
$sumTimeSelect->columns(array(new Expression('SUM(time)')));
$sumTimeSelect->where->addPredicates('gpt.user_id = a.id');
$select = new Select();
$select->from(array('a' => 'users'));
$select->columns(array(
'id',
'name',
'age',
'max_score' => new Expression('?', array($maxScoreSelect)),
'time_played' => new Expression('?', array($sumTimeSelect))
));
$select->order('last_visited DESC');
$select->limit(100);
$select->offset(0);
I have two tables: users and usermeta. The table usermetahas 4 columns: id, user_id, meta_key and meta_value. A user can have many meta data.
I want to get the groups of the first 10 users. So I create a SQL query in Zend framework 2:
$coreSelect = $sql->select()
->from('users')
->limit(10)
->offset(0);
$select = $sql->select()
->from(array('u' => $coreSelect))
->join('usermeta',
'u.user_id = usermeta.user_id',
array(
'meta_key' => 'meta_key',
'meta_value' => 'meta_value',
),
Select::JOIN_LEFT
);
When execute this query, it show up a SQL syntax error. The SQL query string manipulated by Zend framework is like this:
SELECT u.*
FROM (
SELECT * FROM users LIMIT '10' OFFSET '0') AS u
...
It means that Zend framework has added quotes into offset and limit value and it makes the syntax error.
Can anyone please help me to resolve this problem?
This should help you:
http://www.maltblue.com/tutorial/zend-db-sql-creating-joins-and-unions-with-ease
Something that interests you, towards the end, but read all of it is useful.
I'm in the view action of my PhotosController.php. What I want to do is given the id of the current photo I am viewing, create a carousel of photos containing the two photos before and two photos after the current photo with the current photo in the middle (5 in total).
I was pointed to this solution but I can't seem to convert it to CakePHP using $this->Photo->query.
My controller
$this->set('photos', $this->Photo->query("
SELECT id, file FROM photos WHERE id <= $id AND page_id = $page_id ORDER BY id DESC LIMIT 3
UNION ALL
SELECT id, file FROM photos WHERE id > $id AND page_id = $page_id ORDER BY id ASC LIMIT 2
"));
Unfortunately, when I don't see anything when I turn debugging on. id, file, and page_id are all columns in the photos table. Both #id and $page_id are passed to the action from the router. Is my syntax wrong?
EDIT: If I remove the UNION ALL and the second SELECT statement, then the query works fine so it's not an issue with the model not being loaded because it is.
EDIT (workaround): For now I'm doing two queries which is not ideal.
$this->set('photos_before', $this->Photo->find('all', array(
'conditions' => array(
'Photo.page_id' => $page_id,
'Photo.id <' => $id
),
'order' => array('Photo.id ASC'),
'limit' => 2
)));
$this->set('photos_after', $this->Photo->find('all', array(
'conditions' => array(
'Photo.page_id' => $page_id,
'Photo.id >' => $id
),
'order' => array('Photo.id ASC'),
'limit' => 2
)));
I have a contain before hand to only return the fields and associated models I need.
Below is what I want to be displayed and it currently works using the two queries above but I am hoping this can be achieved with a single, Cake-friendly query
My guess is that your original query is invalid SQL. Afaik UNIONS cannot contain multiple 'order by' clauses. As a workaround you may consider to rewrite it to use subqueries like this:
SELECT * FROM (SELECT id, file FROM photos WHERE id <= $id AND page_id = $page_id ORDER BY id DESC LIMIT 3) AS suba
UNION ALL
SELECT * FROM (SELECT id, file FROM photos WHERE id > $id AND page_id = $page_id ORDER BY id ASC LIMIT 2) AS subb
Although I serious think a query like this is far from optimal. Of course, I don't know the way your application works, but it seems that a standard pagination query, with a OFFSET/LIMIT is a more logical approach.
Please take my comment below your question into account; using model->query does NOT automatically handle sanitisation/escaping to prevent SQL injections!
You have to load model as
$this->loadModel('Photo');
Before executing query.
You should create a VIEW in MySQL and then use that as a model, and do a traditional CakePHP find on that.
Read up on creating views in MySQL and then create a model based on that view name.
I have this query which works but when I try to write the equivalent in LINQ I get the incorrect SQL produced.
My query is:
SELECT COUNT(*)
FROM tableName
GROUP BY ColumnId
I've tried writing it as:
tableName.GroupBy(x => x.ColumnId).Count()
But looking in LINQPad it is producing the SQL:
SELECT COUNT(*) AS [value]
FROM (
SELECT NULL AS [EMPTY]
FROM [tableName] AS [t0]
GROUP BY [t0].[ColumnId]
) AS [t1]
What am I doing wrong? Thanks!
Your LINQ query is counting the number of groups but your SQL query is producing the counts by group. You want
var counts = tableName.GroupBy(x => x.ColumnId)
.Select(g => new { g.Key, Count = g.Count() });
to get the counts by group.
Note that if you want exactly the same SQL you want
var counts = tableName.GroupBy(x => x.ColumnId)
.Select(g => g.Count());
The first example above should be a little more useful as it gives the ids of each group as well.
Try tableName.GroupBy(x => x.ColumnId).Select(x => x.Count())