Here is my sql, i am struggling to translate this to laravel 5.8 query builder syntax.
SELECT CC AS CountOfVisits, Count(CC) AS Users
FROM
(
SELECT user_id, count(user_id) AS CC FROM mytable
GROUP BY user_id
) AS CC
GROUP BY CC;
I tried this:
$frequency= DB::connection('mysql2')
->select(DB::raw('CC AS CountOfVisits'), DB::raw('Count(CC) AS Users'))
->from(function($sq)
{
$sq->select(DB::raw('user_id, count(user_id) AS CC FROM '))
->from('mytable')
->groupBy('user_id');
})
->groupBy('CC')
->get();
it errors with
Argument 1 passed to Illuminate\Database\Connection::prepareBindings()
must be of the type array, object given, called in
/var/app/portal/vendor/laravel/framework/src/Illuminate/Database/Connection.php
on line 665
Any help would be great thanks
I think the problem you're having is that the returned connection is expecting string for the full query with additional bindings on the second parameter. You can still build it using illuminate's query builder first if you like, then run the select using the generated string.
$query = DB::query()
->select('CC AS CountOfVisits', DB::raw('count(CC) AS Users'))
->fromSub(function (\Illuminate\Database\Query\Builder $query) {
$query->select('user_id', DB::raw('count(user_id) AS CC '))
->from('mytable')
->groupBy('user_id');
}, 'CC')
->groupBy('CC');
$result = DB::connection()->select($query->toSql());
Related
I am using a doctrine 2 in symfony3.4 and I have a complex query which is :
$query = $this->createQueryBuilder(
'SELECT id FROM AppBundle:Room WHERE id NOT IN ( SELECT room_id FROM AppBundle:Bookings WHERE NOT ( checkOut <= :check_in OR checkIn >= :check_out ) ) ORDER BY id'
)
->setParameter('check_in', $request->query->get('check-in'))
->setParameter('check_out', $request->query->get('check-out'))
->getQuery();
return $rooms = $query->execute() ;
my problem is when I execute this query , I get an error which is :
[Syntax Error] line 0, col 7: Error: Expected IdentificationVariable | ScalarExpression | AggregateExpression | FunctionDeclaration | PartialObjectExpression | "(" Subselect ")" | CaseExpression, got 'SELECT'
The createQueryBuilder method expects a string as first parameter but you are providing a full query statement and the result would be something like this:
select select id... from table
an that raises an exception the bold part is your query inside the createQueryBuilder method.
Try this instead:
$this->createQueryBuilder('alias')->addSelect('alias.id')
->where(...)
->orderBy(...)
Hope it helps
EDIT
inside the where you put what is after the where in your old code but with the query builder you can build your query without the sql and let doctrine build the query for you
check this doc
I'm trying to execute the following query using knex.js and MySql
SELECT
m.id,
TIME(date_created) AS `timestamp`,
u.username,
m.`message`
FROM
`messages` AS m
INNER JOIN users AS u ON u.id = m.user_id
WHERE
m.game_id IS NULL
AND m.`date_created` > DATE_SUB(
CURRENT_TIMESTAMP (),
INTERVAL 12 HOUR
)
ORDER BY
m.`date_created` ASC
LIMIT 50
For proper handling expressions in where closure such as DATE_SUB(CURRENT_TIMESTAMP(), INTERVAL 12 HOUR) according to documentation there is whereRow() method in knex.
I tried to use select() method as
select('messages.id', 'TIME(date_created) AS timestamp', 'users.username', 'messages.message')
But knex masks TIME(date_created) expression in a way it should to be a column name. Does anybody know a way to use a custom expressions in selects?
I did not found exact answer on my question but I've found a solution which allows me to move forward. I created separate model which uses standard Bookshelf(knex) export:
var Bookshelf = require('bookshelf')(knex);
module.exports.DB = Bookshelf;
And created separate method in that model where I could use DB.knex.raw() for masking DB expressions in SELECT. So I became able to write the query above in the following way:
var DB = require('./../db').DB;
var Messages = DB.Model.extend({
tableName: 'messages',
hasTimestamps: false,
idAttribute: 'id'
},
{
getMessagesHistory: function (gameId) {
return this.query().select('messages.id', DB.knex.raw('TIME(date_created) AS timestamp'), 'users.username', 'messages.message')
.innerJoin('users', 'messages.user_id', 'users.id')
.whereRaw("messages.game_id " + (gameId == 0 ? "IS NULL" : "= " + gameId))
.andWhereRaw("messages.date_created > DATE_SUB(CURRENT_TIMESTAMP(), INTERVAL 12 HOUR)")
.orderBy('messages.date_created', 'ASC')
.limit(50);
}
}
);
module.exports = Messages;
You can wrap any argument with knex.raw() to tell the framework that it's a raw piece of SQL:
select(
'messages.id',
knex.raw('TIME(date_created) AS timestamp'),
'users.username',
'messages.message',
)
See http://knexjs.org/#Raw-Bindings
I have a query that will display columns with duplicate or with more than 1 values.I can display it using sql
select date_created,loan_id,count(1) as cnt
from collections
group by date_created,loan_id
having count(1)>1;
I want that to convert to Doctrine 1 query,I tried
public function getDuplicateDatePayment() {
$q = $this->createQuery('c')
->select('c.date_created,c.loan_id,c.count(1) as cnt')
->groupBy('c.date_created','c.loan_id')
->having('c.count(1) > 1');
return $q->execute();
}
But it only return errors.Any Idea on how to correctly convert the said working sql into a doctrine 1 query?
SQLSTATE[42000]: Syntax error or access violation: 1630 FUNCTION c.count does not exist. Check the 'Function Name Parsing and Resolution' section in the Reference Manual. Failing Query: "SELECT c.id AS c__id, c.date_created AS c__date_created, c.loan_id AS c__loan_id, c.count(1) AS c__0, c.count(1) AS c__0 FROM collections c GROUP BY c.date_created HAVING c.count(1) > 1"
I hope the problem may be with count. Try the following
public function getDuplicateDatePayment() {
$q = $this->createQuery('c')
->select('c.date_created,c.loan_id,count(c.1) as cnt')
->groupBy('c.date_created','c.loan_id')
->having('c.count(1) > 1');
return $q->execute();
}
I'm working on a school project and I'm trying to get a query working.
SELECT *
FROM `ziekmeldingen` AS a
WHERE NOT EXISTS
(SELECT *
FROM `ziekmeldingen` AS b
WHERE `ziek` = 1
AND a.personell_id = b.personell_id)
Name of the model: ZiekmeldingenModel
I tried 2 things, both dont work ->
$medewerkers = ZiekmeldingenModel::whereNotExists(function($query)
{
$query->select()->from('ziekmeldingen AS b')->where('ziek', '=', '1')->where('ziekmeldingen.personell_id', '=', 'b.personell_id');
})->get();
return $medewerkers;
And
$medewerkers = ZiekmeldingenModel::raw('SELECT * FROM `ziekmeldingen` as a WHERE NOT EXISTS ( SELECT * FROM `ziekmeldingen` as b WHERE `ziek` = 1 AND a.personell_id = b.personell_id)')->get();
Both of them give back all the results from the table while it should only give back 1 result (I've tested the original query, it works).
EDIT: Forgot to mention I'm using relationships in the model. So the raw solution probably won't work anyway
Found the answer. Had to use a combo of both the things I tried.
$medewerkers = ZiekmeldingenModel::select()
->from(DB::raw('`ziekmeldingen` AS a'))
->whereNotExists(function($query){
$query->select()
->from(DB::raw('`ziekmeldingen` AS b'))
->whereRaw('`ziek` = 1 AND a.personell_id = b.personell_id');
})->get();
return $medewerkers;
Thanks for any help and effort.
Definitely no need for select(). Also no raw in from or whereRaw needed.
The only unusual thing here is raw piece in the where, since you don't want table.field to be bound and treated as string. Also, you can use whereRaw for the whole clause in case you have your tables prefixed, otherwise you would end up with something like DB_PREFIX_a.personell_id, so obviously wrong.
This is how you do it:
$medewerkers = ZiekmeldingenModel::from('ziekmeldingen AS a')
->whereNotExists(function ($q) {
$q->from('ziekmeldingen AS b')
->where('ziek', 1)
->where('a.personell_id', DB::raw('b.personell_id'))
// or:
// ->whereRaw('a.personell_id = b.personell_id');
})->get();
Use the take() method though if you're not ordering your results the record you get back could be any of the results.
$medewerkers = ZiekmeldingenModel::raw('SELECT * FROM `ziekmeldingen` as a WHERE NOT EXISTS ( SELECT * FROM `ziekmeldingen` as b WHERE `ziek` = 1 AND a.personell_id = b.personell_id)')->take(1)->get();
I have this mysql query:
SELECT
freeAnswers.*,
(SELECT `districtCode`
FROM `geodatas`
WHERE `zipCode` = clients.zipCode
GROUP BY `zipCode`
LIMIT 0, 1) as districtCode,
clients.zipCode,
clients.gender,
clients.startAge,
clients.endAge,
clients.mail,
clients.facebook,
surveys.customerId,
surveys.activityId,
surveys.name as surveyName,
customers.companyName,
activities.name as activityName
FROM freeAnswers,
clients,
surveys,
customers,
activities
WHERE freeAnswers.surveyId = surveys.id
AND surveys.customerId = customers.id
AND activities.id = surveys.activityId
AND clients.id = freeAnswers.clientId
AND customers.id = 1
ORDER BY activityName asc
LIMIT 0, 10
the query is correct on my mysql server but when I try to use it in Zend Framework 1.11 model
I get this error: Mysqli prepare error: Operand should contain 1 column(s)
Please, could anyone help me to make it run well?
Best Regards,
Elaidon
Here is some code that should work. Zend_Db_Select doesn't really provide a way to select from multiple tables in the FROM clause without using a JOIN so this feels a bit hackish to me in regards to one small part of the query. Your best bet will probably be to rewrite the query using JOINs where appropriate.
$subselect = $db->select()
->from('geodatas', 'districtCode')
->where('zipCode = clients.zipCode')
->group('zipCode')
->limit(1, 0);
$from = $db->quoteIdentifier('freeAnswers') . ', ' .
$db->quoteIdentifier('clients') . ', ' .
$db->quoteIdentifier('surveys') . ', ' .
$db->quoteIdentifier('customers') . ', ' .
$db->quoteIdentifier('activities');
$select = $db->select()
->from(array('activities' => new Zend_Db_Expr($from)),
array('freeanswers.*',
'districtCode' =>
new Zend_Db_Expr('(' . $subselect . ')'),
'clients.zipCode', 'clients.gender', 'clients.startAge',
'clients.endAge', 'clients.mail', 'clients.facebook',
'clients.customerId', 'clients.activityId',
'surveyName' => 'surveys.name', 'customers.companyName',
'activityName' => 'activities.name'))
->where('freeAnswers.surveyId = surveys.id')
->where('surveys.customerId = customers.id')
->where('activities.id = surveys.activityId')
->where('clients.id = freeAnswers.clientId')
->where('customers.id = ?', 1)
->order('activityName ASC')
->limit(10, 0);
The only reason I say it is hackish is because of the line:
->from(array('activities' => new Zend_Db_Expr($from)),
Since from() really only works with one table, I create a Zend_Db_Expr and specify the correlation as the last table name in the expression. If you don't pass a Zend_Db_Expr, it will either quote your comma separated table name incorrectly, or if you pass an array of table names, it just uses the first. When you pass a Zend_Db_Expr with no name, it defaults to use AS t which also doesn't work in your case. That is why I put it as is.
That returns the exact SQL you provided except for the last thing mentioned. Here is actually what it returns:
SELECT
`freeanswers`.*,
(SELECT `geodatas`.`districtCode`
FROM `geodatas`
WHERE (zipCode = clients.zipCode)
GROUP BY `zipCode`
LIMIT 1) AS `districtCode`,
`clients`.`zipCode`,
`clients`.`gender`,
`clients`.`startAge`,
`clients`.`endAge`,
`clients`.`mail`,
`clients`.`facebook`,
`clients`.`customerId`,
`clients`.`activityId`,
`surveys`.`name` AS `surveyName`,
`customers`.`companyName`,
`activities`.`name` AS `activityName`
FROM `freeAnswers`,
`clients`,
`surveys`,
`customers`,
`activities` AS `activities`
WHERE (freeAnswers.surveyId = surveys.id)
AND (surveys.customerId = customers.id)
AND (activities.id = surveys.activityId)
AND (clients.id = freeAnswers.clientId)
AND (customers.id = 1)
ORDER BY `activityName` ASC
LIMIT 10
So that will work but eventually you will want to rewrite it using JOIN instead of specifying most of the WHERE clauses.
When dealing with subqueries and Zend_Db_Select, I find it easy to write each subquery as their own queries before writing the final query, and just insert the subqueries where they need to go and Zend_Db handles the rest.
Hope that helps.