I have the following query in rails...
#registrations = Registration.where(Orientation.where(class_date: #start_date..#end_date))
The query itself does not throw an error, however if I try to inspect #registrations do anything with the variable I get the error...
Cannot visit ActiveRecord::Relation
Any ideas?
Orientation.where(class_date: #start_date..#end_date)
does the range query you like
SELECT * FROM orientations WHERE class_date BETWEEN <start_date> AND <end_date>
UPDATE
Registration.where(created_at: #start_date..#end_date).
joins(:orientation).
where('orientations.created_at' => #start_date..#end_date)
will make the following SQL which I think is what you need
SELECT registrations.* FROM registrations INNER JOIN orientations ON orientations.id = registrations.orientation_id WHERE (registrations.created_at BETWEEN '2014-02-17 16:01:41' AND '2014-02-19 16:01:41') AND (orientations.created_at BETWEEN '2014-02-17 16:01:41' AND '2014-02-19 16:01:41')
Related
I am trying to filter one table Payments by a field on the associated table Invoices.
Using the function matching() on the query object filters correctly but causes duplicate rows. It seemed like the solution was using distinct(), but calling distinct(Payments.id) results in an invalid query. I'm doing the following in a controller action.
$conditions = [
'Payments.is_deleted =' => false
];
$args = [
'conditions' => $conditions,
'contain' => ['Invoices', 'Invoices.Clients'],
];
$payments = $this->Payments->find('all', $args);
if($issuer) {
// This causes duplicate rows
$payments->matching('Invoices', function ($q) use ($issuer) {
return $q->where(['Invoices.issuer_id' => $issuer['id']]);
});
// $payments->distinct('Payments.id'); // Causes a mysql error
}
Am I correct in thinking that distinct() is what I need, and if so any idea what's missing to make it work?
I'm getting the following mysql error when uncommenting the line above:
Error: SQLSTATE[42000]: Syntax error or access violation: 1055 Expression #8 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'InvoicesPayments.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
Full query:
SELECT
PAYMENTS.ID AS `PAYMENTS__ID`,
PAYMENTS.CREATED AS `PAYMENTS__CREATED`,
PAYMENTS.MODIFIED AS `PAYMENTS__MODIFIED`,
PAYMENTS.DATE_REGISTERED AS `PAYMENTS__DATE_REGISTERED`,
PAYMENTS.USER_ID AS `PAYMENTS__USER_ID`,
PAYMENTS.AMOUNT AS `PAYMENTS__AMOUNT`,
PAYMENTS.IS_DELETED AS `PAYMENTS__IS_DELETED`,
INVOICESPAYMENTS.ID AS `INVOICESPAYMENTS__ID`,
INVOICESPAYMENTS.INVOICE_ID AS `INVOICESPAYMENTS__INVOICE_ID`,
INVOICESPAYMENTS.PAYMENT_ID AS `INVOICESPAYMENTS__PAYMENT_ID`,
INVOICESPAYMENTS.PART_AMOUNT AS `INVOICESPAYMENTS__PART_AMOUNT`,
INVOICES.ID AS `INVOICES__ID`,
INVOICES.CREATED AS `INVOICES__CREATED`,
INVOICES.MODIFIED AS `INVOICES__MODIFIED`,
INVOICES.IS_PAID AS `INVOICES__IS_PAID`,
INVOICES.IS_DELETED AS `INVOICES__IS_DELETED`,
INVOICES.CLIENT_ID AS `INVOICES__CLIENT_ID`,
INVOICES.ISSUER_ID AS `INVOICES__ISSUER_ID`,
INVOICES.NUMBER AS `INVOICES__NUMBER`,
INVOICES.SUBTOTAL AS `INVOICES__SUBTOTAL`,
INVOICES.TOTAL AS `INVOICES__TOTAL`,
INVOICES.DATE_REGISTERED AS `INVOICES__DATE_REGISTERED`,
INVOICES.CURRENCY AS `INVOICES__CURRENCY`,
INVOICES.RECEIVER_NAME AS `INVOICES__RECEIVER_NAME`,
INVOICES.RECEIVER_RFC AS `INVOICES__RECEIVER_RFC`,
INVOICES.EMAIL_SENDER AS `INVOICES__EMAIL_SENDER`,
INVOICES.PDF_PATH AS `INVOICES__PDF_PATH`
FROM
PAYMENTS PAYMENTS
INNER JOIN
INVOICES_PAYMENTS INVOICESPAYMENTS
ON PAYMENTS.ID = (
INVOICESPAYMENTS.PAYMENT_ID
)
INNER JOIN
INVOICES INVOICES
ON (
INVOICES.ISSUER_ID = :C0
AND INVOICES.ID = (
INVOICESPAYMENTS.INVOICE_ID
)
)
WHERE
(
PAYMENTS.IS_DELETED = :C1
AND PAYMENTS.DATE_REGISTERED >= :C2
AND PAYMENTS.DATE_REGISTERED <= :C3
)
GROUP BY
PAYMENT_ID
ORDER BY
PAYMENTS.DATE_REGISTERED ASC
That behavior is expected, as matching will use an INNER join, and yes, grouping is how you avoid duplicates:
As this function will create an INNER JOIN, you might want to consider calling distinct on the find query as you might get duplicate rows if your conditions don’t exclude them already. This might be the case, for example, when the same users comments more than once on a single article.
Cookbook > Database Access & ORM > Query Builder > Loading Associations > Filtering by Associated Data
As the error message states, your MySQL server is configured to use the strict only_full_group_by mode, where your query is invalid. You can either disable that strict mode as mentioned by Akash prajapati (which can come with its own problems, as MySQL is then allowed to pretty much pick values of a group at random), or you could change how you query things in order to conform to the strict mode.
In your case where you need to group on the primary key, you could simply switch to using innerJoinWith() instead, unlike matching() this will not add any fields of that association to the SELECT list, and things should be fine in strict mode, as everything else is functionally dependent:
In cases where you would group on a key that would break functional dependency detection, one way to solve that could for example be to use a subquery for filtering, one that only selects that key, something along the lines of this:
$conditions = [
'Payments.is_deleted =' => false
];
$payments = $this->Payments
->find()
->contain(['Invoices.Clients']);
if($issuer) {
$matcherQuery = $this->Payments
->find()
->select(['Payments.some_other_field'])
->where($conditions)
->matching('Invoices', function ($q) use ($issuer) {
return $q->where(['Invoices.issuer_id' => $issuer['id']]);
})
->distinct('Payments.some_other_field');
$payments->where([
'Payments.some_other_field IN' => $matcherQuery
]);
} else {
$payments->where($conditions);
}
This will result in a query similar to this, where the outer query can then select all the fields you want:
SELECT
...
FROM
payments
WHERE
payments.some_other_field IN (
SELECT
payments.some_other_field
FROM
payments
INNER JOIN
invoices_payments ON
payments.id = invoices_payments.payment_id
INNER JOIN
invoices ON
invoices.issuer_id = ...
AND
invoices.id = invoices_payments.invoice_id
WHERE
payments.is_deleted = ...
GROUP BY
payments.some_other_field
)
The problem with sql_mode value in mysql so you need to set the sql_mode value as blank and then you can try and working fine for you.
SET GLOBAL sql_mode=(SELECT REPLACE(##sql_mode,'ONLY_FULL_GROUP_BY',''));
Please let me know still anything else.
I had the same issue, but was too afraid to set the sql_mode as mentioned by #Akash and also too much in a hurry to restructure the query. So I decided to use the inherited Collection method indexBy()
https://book.cakephp.org/4/en/core-libraries/collections.html#Cake\Collection\Collection::indexBy
$resultSetFromYourPaymentsQuery = $resultSetFromYourPaymentsQuery->indexBy('id');
It worked like a charm and it is DB independent.
EDIT: After some more tinkering, this might not be practical for all use cases. Replacing matching with innerJoinWith as proposed in the accepted answer will probably solve it in more generalized manner.
I have written a join query in MySQL which works well and shows the result.
I am trying to write a MySQL query that shows 2 additional columns with some calculations
If isPercent=1 then
New Column1=price*currentPercent/100
New Column2=LineItemQuantity*price
I tried to write this query in PHP but since there are 100,000s records it is timing out.
Here is MySQL query and the results shown below
Select
wl.LineItems_LineItemID,
wl.LineItemQuantity,
pj.IsPercent,
pj.CurrentPercent,
pj.CurrentRate,
cb.Price
from
WorkOrderLineItems wl,
PayScaleLoaclJObCodes pj,
ClientBillingRates cb
where
wl.LineItems_LineItemID=pj.JobCodeID
AND wl.LineItems_LineItemID=cb.ClientBillingRates_ID
AND pj.PayScalesLocal_ID='33'
I would write the query this way:
SELECT
wl.LineItems_LineItemID,
wl.LineItemQuantity,
pj.IsPercent,
pj.CurrentPercent,
pj.CurrentRate,
cb.Price,
IF(pj.IsPercent=1, cb.Price*pj.CurrentPercent/100, NULL) AS `New Column 1`,
IF(pj.IsPercent=1, wl.LineItemQuantity*cb.Price, NULL) AS `New Column 2`
FROM
WorkOrderLineItems wl
JOIN PayScaleLoaclJObCodes pj ON wl.LineItems_LineItemID = pj.JobCodeID
JOIN ClientBillingRates cb ON wl.LineItems_LineItemID = cb.ClientBillingRates_ID
WHERE pj.PayScalesLocal_ID = '33'
As in the comments above, I encourage you to use JOIN syntax instead of relying on old-fashioned comma-style joins.
As for the query timing out, I would guess that you don't have the right indexes to support this query. If you want help with query optimization, you should run SHOW CREATE TABLE <tablename> for each table in your query, and post the output in your question.
I want use where in $query
$query->where(['and', "SUM(opportunity_conditions.money)>=10", "SUM(opportunity_conditions.money)<=100"]);
This is my $query :
$query = (new \yii\db\Query())->select(['SUM(opportunity_conditions.money),(opportunity_conditions.money)', 'opportunity.id', 'opportunity.logo', 'profile_details.user_id', 'opportunity.name', 'profile_details.co_name', 'opportunity.address', 'opportunity.project_type_id', 'opportunity.state_id'])->from('opportunity ')->innerJoin('profile_details', 'opportunity.user_id=profile_details.user_id')->where('opportunity_conditions.who=2')->innerJoin('opportunity_conditions', 'opportunity.id=opportunity_conditions.opportunity_id')->addGroupBy('opportunity.id')->orderBy('opportunity.id desc');
I need my query has result where:
SUM(opportunity_conditions.money)>=10 and SUM(opportunity_conditions.money)<=100
This is my error :
SQLSTATE[HY000]: General error: 1111 Invalid use of group function
The SQL being executed was:
SELECT SUM(opportunity_conditions.money),
(opportunity_conditions.money),
opportunity.id,
opportunity.logo,
profile_details.user_id,
opportunity.name,
profile_details.co_name,
opportunity.address,
opportunity.project_type_id,
opportunity.state_id
FROM opportunity
INNER JOIN profile_details
ON opportunity.user_id=profile_details.user_id
INNER JOIN opportunity_conditions
ON opportunity.id=opportunity_conditions.opportunity_id
WHERE
((SUM(opportunity_conditions.id)>=1) AND
(SUM(opportunity_conditions.id)<=1)) AND
(opportunity.id IN (27, 28))
GROUP BY opportunity.id
ORDER BY opportunity.id DESC
Try replacing where() with having(). Then add opportunity_conditions.who to the select() list.
Ok I think you can figure out this way.
first check the query is correct? we can get query from following command
var_dump($query->createCommand()->rawSql);
Now check this query or run this in database, remake the query if you a find mistake.
I have a SQL query I would like to use in Doctrine2.
My query, goes to the dabatase, does a GROUP BY user state and COUNT the number of users per state.
Then I'm trying to join a table to COUNT all users and make a percent for every state.
return $this->getEntityManager()
->createQuery("
SELECT COUNT(u.id) as total,
(100*(COUNT( u.id ) / total_users.total)) as percent
FROM UserBundle:User u,
(SELECT COUNT(*) as total
FROM UserBundle:User) as total_users
LEFT JOIN u.idUserEstado ue
GROUP BY u.idUserEstado")
->getResult();
The problem is, when I run the Doctrine2 query I get an exception:
[Semantical Error] line 0, col 397 near
'(SELECT COUNT(': Error: Class '(' is not defined.
Doctrine does not recognize that SELECT on the FROM clause.
Select on the from clause are not handled by doctrine 2
There is a closed (and not accepted) feature request on doctrine's jira : http://www.doctrine-project.org/jira/browse/DDC-2793
DQL is about querying objects. Supporting subselects in the FROM
clause means that the DQL parser is not able to build the result set
mapping anymore (as the fields returned by the subquery may not match
the object anymore). This is why it cannot be supported (supporting it
only for the case you run the query without the hydration is a no-go
IMO as it would mean that the query parsing needs to be dependant of
the execution mode).
(SELECT COUNT( * ) as total FROM UserBundle:User) as total_users
COUNT(*) may not exists in DQL. Try COUNT(u.id), the results will be the same. You also have the possibility to try this in an EntityRepository :
$qb->select(array(
'count(u.id) as total',
'(100*(count(u.id)/total_users.total)) as percent',
'select count(u.id) as total_users) as total_users'))
->from('UserBundle:User')
->leftJoin('u.idUserEstado','ue')
->groupBy('u.idUserEstado');
return $qb->getQuery()->getResult();
Source: Google UserGroup issue
the
... FROM UserBundle:User u, ...
is strange. Maybe it can't find the class User.
MySQL Server Version: Server version: 4.1.14
MySQL client version: 3.23.49
Tables under discussion: ads_list and ads_cate.
Table Relationship: ads_cate has many ads_list.
Keyed by: ads_cate.id = ads_list.Category.
I am not sure what is going on here, but I am trying to use COUNT() in a simple agreggate query, and I get blank output.
Here is a simple example, this returns expected results:
$queryCats = "SELECT id, cateName FROM ads_cate ORDER BY cateName";
But if I modify it to add the COUNT() and the other query data I get no array return w/ print_r() (no results)?
$queryCats = "SELECT ads_cate.cateName, ads_list.COUNT(ads_cate.id),
FROM ads_cate INNER JOIN ads_list
ON ads_cate.id = ads_list.category
GROUP BY cateName ORDER BY cateName";
Ultimately, I am trying to get a count of ad_list items in each category.
Is there a MySQL version conflict on what I am trying to do here?
NOTE: I spent some time breaking this down, item by item and the COUNT() seems to cause the array() to disappear. And the the JOIN seemed to do the same thing... It does not help I am developing this on a Yahoo server with no access to the php or mysql error settings.
I think your COUNT syntax is wrong. It should be:
COUNT(ads_cate.id)
or
COUNT(ads_list.id)
depending on what you are counting.
Count is an aggregate. means ever return result set at least one
here you be try count ads_list.id not null but that wrong. how say Myke Count(ads_cate.id) or Count(ads_list.id) is better approach
you have inner join ads_cate.id = ads_list.category so Count(ads_cate.id) or COUNT(ads_list.id) is not necessary just count(*)
now if you dont want null add having
only match
SELECT ads_cate.cateName, COUNT(*),
FROM ads_cate INNER JOIN ads_list
ON ads_cate.id = ads_list.category
GROUP BY cateName
having not count(*) is null
ORDER BY cateName
all
SELECT ads_cate.cateName, IFNULL(COUNT(*),0),
FROM ads_cate LEFT JOIN ads_list
ON ads_cate.id = ads_list.category
GROUP BY cateName
ORDER BY cateName
Did you try:
$queryCats = "SELECT ads_cate.cateName, COUNT(ads_cate.id)
FROM ads_cate
JOIN ads_list ON ads_cate.id = ads_list.category
GROUP BY ads_cate.cateName";
I am guessing that you need the category to be in the list, in that case the query here should work. Try it without the ORDER BY first.
You were probably getting errors. Check your server logs.
Also, see what happens when you try this:
SELECT COUNT(*), category
FROM ads_list
GROUP BY category
Your array is empty or disappear because your query has errors:
there should be no comma before the FROM
the "ads_list." prefix before COUNT is incorrect
Please try running that query directly in MySQL and you'll see the errors. Or try echoing the output using mysql_error().
Now, some other points related to your query:
there is no need to do ORDER BY because GROUP BY by default sorts on the grouped column
you are doing a count on the wrong column that will always give you 1
Perhaps you are trying to retrieve the count of ads_list per ads_cate? This might be your query then:
SELECT `ads_cate`.`cateName`, COUNT(`ads_list`.`category`) `cnt_ads_list`
FROM `ads_cate`
INNER JOIN `ads_list` ON `ads_cate`.`id` = `ads_list`.`category`
GROUP BY `cateName`;
Hope it helps?