Laravel group by and SUM - mysql

Having trouble getting my head around this one, it likely doesn't help I don't have any SQL 'group by' experience.
I have a table that has a transaction_type column and an amount column. Basically I am trying to use SQL/Eloquent to get the following in a single query (if possible, I know this isn't sql):
add = SUM(amount) where transaction_type == 1
delete = SUM(amount) WHERE transaction_type == 2
return from MySQL: add-delete
I'm assuming this would be done using groupby, but despite my best efforts I haven't be able to find a solution by reading the sql documentation.
I think I have got it using plain SQL, but how would I convert this to Eloquent:
SELECT `transaction_type`, SUM(`amount`) FROM `credit_logs` WHERE `to_group_id` = '1'

I can't help you with eloquent, but your query should be something like this:
SELECT
SUM(CASE WHEN transaction_type = 1 THEN amount ELSE NULL END)
-
SUM(CASE WHEN transaction_type = 2 THEN amount ELSE NULL END)
FROM credit_logs
WHERE to_group_id = 1;
or for all id's you wish to group by:
SELECT
SUM(CASE WHEN transaction_type = 1 THEN amount ELSE NULL END)
-
SUM(CASE WHEN transaction_type = 2 THEN amount ELSE NULL END)
FROM credit_logs
GROUP BY to_group_id;
Easiest would be, if you'd find a way to just execute a query with eloquent. Never understood why someone wants to transform a nice readable query into some "improved" syntax of a framework.

Related

Reduce the number of queries

I have seperate queries but i need to reduce the no so put all in one
select count(applicant_id) as registered from student_application where filter_status=0 AND
select count(applicant_id) as filer_select from student_application where filter_status=1 AND
select count(applicant_id) as filter_reject from student_application where filter_status=2
but this shows some errors
Use CASE expression.
Query
select
count(case when filter_status = 0 then applicant_id else null end) as registered,
count(case when filter_status = 1 then applicant_id else null end) as filer_select,
count(case when filter_status = 2 then applicant_id else null end) as filer_reject
from student_application;
SQL Fiddle
You could also use group_by, with the where clause if you're looking for a subset rather than all possible values of filter_status:
SELECT filter_status, COUNT(*)
FROM student_application
WHERE filter_status in (0, 1, 2)
GROUP BY filter_status;

How to get multiple SUM with one SQL query?

I am wondering how to fix this query.
SELECT
SUM(`month_using`) used,
SUM(`month_cash`) paycash,
SUM(`month_profit` CASE WHEN `id` <> 'system' THEN 1 ELSE 0 END) profit
FROM `_using_month`
WHERE MONTH(`month_date`) = {month} AND YEAR(`month_date`) = {year}
Thanks
Use Group by clause to get multiple SUM:
For Example:
SELECT YEAR(month_date), MONTH(month_date),
SUM(month_using) used, SUM(month_cash) paycash,
SUM(month_profit CASE WHEN id <> 'system' THEN 1 ELSE 0 END) profit
FROM _using_month
GROUP BY YEAR(month_date), MONTH(month_date)

MySQL sum on condition does not work in a view

In MySQL (v5.5), the value of numNotCast, numInFavor is always 0 when selecting all rows of the view. If the select statement is executed alone (not in the view), it works as expected returning the correct count of the the number of rows in the vote column equal to value 'notcast' and 'infavor'.
CREATE OR REPLACE
VIEW `Stats` AS
select
sum(case when `p`.`vote` = 'notcast' then 1 else 0 end) AS `numNotCast`,
sum(case when `p`.`vote` = 'infavor' then 1 else 0 end) AS `numInFavor`
from
(`Debate` `d`
join `Participant` `p` ON ((`d`.`debateId` = `p`.`debateId`)))
group by `d`.`debateId`
Is this a limitation on MySQL views? How do you accomplish this conditional summing function in the view?
Then your statement is correct as SQLFiddle confirms, so your problem is probably somewhere else
CREATE OR REPLACE VIEW Stats AS
select
Debate.debateId,
sum(case when Participant.vote='notcast' then 1 else 0 end) as numNotCast,
sum(case when Participant.vote='infavor' then 1 else 0 end) as numInFavor
from
Debate
inner join
Participant on Participant.debateId = Debate.debateId
group by
Debate.debateId
Updated after the clarification
There are many limitations in MySQL views, but I don't think this is one of them.
I think it is strange that the name of the view is in single quotes. That might be allowed, but the view may not be doing what you want. Try this:
CREATE OR REPLACE VIEW `Stats` AS
select sum(case when `p`.`vote` = 'notcast' then 1 else 0 end) AS `numNotCast`
from `Debate` `d` join
`Participant` `p`
ON `d`.`debateId` = `p`.`debateId`
group by `d`.`debateId`;
By the way, in MySQL, you can simplify the select to:
select sum(p.vote = 'notcast') as numNotCast

MySQL Combining Multiple Count Queries

I have the following query:
SELECT COUNT(package) as advanced_count FROM users WHERE package = '2' AND site_url is NOT NULL;
What I want to do is have 2 more queries to get the basic_count and then the total_count which is basic + advanced.
My other basic query is:
SELECT count(package) as basic_count FROM users WHERE package = '1' AND site_url is NOT NULL
But I'm not sure how to combine the two so it is just one query, and then plus adding the total number in there as well.
I hope someone can point me in the right directions.
Thank you!
SELECT SUM(CASE WHEN package = '2' THEN 1 ELSE 0 END) AS advanced_count,
SUM(CASE WHEN package = '1' THEN 1 ELSE 0 END) AS basic_count,
COUNT(*) AS total_count
FROM users
WHERE site_url IS NOT NULL
AND package IN ('1', '2');

Optimise SQL query for the report

This is SQL query I wrote, it work fine but it is slow.
SELECT D.Username,
SUM(CASE WHEN D.type = 'Yes' THEN 1 ELSE 0 END) as Yes,
SUM(CASE WHEN D.type = 'No' THEN 1 ELSE 0 END) as No,
SUM(CASE WHEN D.type = '' THEN 1 ELSE 0 END) as Other,
SUM(CASE WHEN S.mobile IS NULL THEN 0 ELSE 1 END) as Sales,
COUNT(*) as TOTAL FROM dairy as D
LEFT JOIN (SELECT DISTINCT mobile FROM sales) as S on D.MobileNo = S.mobile
WHERE source = 'Network' AND UNIX_TIMESTAMP(CheckDate) >= 1309474800 AND UNIX_TIMESTAMP(CheckDate) <= 1309561200
group by D.Username order by TOTAL DESC
As you can see it count number of Yes, No, Other and the matching MobileNo (D.MobileNo = S.mobile) sale.
I have tried adding index to type, username, mobile, MobileNO, CheckDate and source - the performance did not improve much.
Three points to notice in your query:
1. There's a chance the `LEFT JOIN` is giving you performance issues.
However, you need it, since it is possible that there are D.MobileNo values that will not be present in SELECT DISTINCT mobile FROM sales. Any other work around (yes, there are options) will most likely decrease performance. But your performance might be improved by observing the next items.
2. Make sure you have indexes in the key columns:
D.type
S.mobile
D.MobileNo
D.Username
D.Source
D.CheckDate
3. You might be having problems with filtering by `UNIX_TIMESTAMP(CheckDate)`
This might be the key issue. You might be having problems with filtering by UNIX_TIMESTAMP(CheckDate) instead of CheckDate, specially if Dairy has a large amount of records. The problem is that even if you have an index for CheckDate, it will probably not be used because of the function. Try to filter by CheckDate itself.
If this is time critical it can also make sense to store more data.
Here this means that you add INT columns for YesValue, NoValue, OtherValue and fill them with 0 or 1 in your application. By doing this you can remove the case calculations from your SELECT-part.
Also please post all indexes currently available and as the comments say the CREATE-statement for the table.