Mysql Select group by and without group by in one query - mysql

How can I select group by and without group by in one select query? I have a query like this
SELECT date, sum(total) as quotation_total
FROM suspended_bills
WHERE type='quotation'
GROUP BY YEAR(date), MONTH(date)
Here it is taking a group by year and month but I want a sum(total) without group by year and month. So I am able to get full sum(total) without a division of month and year.
This is not a duplicate entry as rollup is generating extra rows that I dont need, I only need the total of sum, so when I run this query with rollup it gave me more rows that is not desired. So all is wrong with roll up query.

In MySQL, the easiest way is a join or subquery:
select YEAR(sb.date), MONTH(sb.date), sum(sb.total) as quotation_total,
t.total_total
from suspended_bills sb cross join
(select sum(total) as total_totla
from suspended_bills
where type = 'quotation'
) t
where sb.type = 'quotation'
group by YEAR(sb.date), MONTH(sb.date), t.total_total;

Related

Select query with calculated field that uses subquery with multiple conditions

Three Tables:
COST_SAVINGS: COST_SAVINGS_ID, ONE_TIME_CREDIT, CREATION_DATE, INVOICE_ID (FK to Invoice table)
INVOICE: INVOICE_ID, INVOICE_CURRENCY_CODE
EXCHANGE_RATE: CURRENCY_RATE, CURRENCY_DATE
I'm reporting on Cost Savings (the first table). The challenge is that each cost savings amount can be in a different currency so I need a field that shows the converted amount based on the currency from the invoice table and a matching month / year between the Exchange.Ex_Date and Cost_Savings.Create_Date.
I'm getting an error that states:
single-row subquery returns more than one row
This is what I have so far:
SELECT
COST_SAVINGS.COST_SAVINGS_ID,
COST_SAVINGS.CLAIM_TYPE,
COST_SAVINGS.COMMENTS,
COST_SAVINGS.COST_SAVINGS_STATUS,
COST_SAVINGS.CREATION_DATE,
COST_SAVINGS.DESCRIPTION,
COST_SAVINGS.ONE_TIME_CREDIT AS CREDIT_IN_NATIVE_CURRENCY,
FINANCE_INVOICE.CURRENCY_CODE,
COST_SAVINGS.ONE_TIME_CREDIT *
(SELECT EXCHANGE_RATE.CURRENCY_RATE
FROM EXCHANGE_RATE
WHERE EXTRACT (MONTH FROM COST_SAVINGS.CREATION_DATE) = EXTRACT (MONTH FROM EXCHANGE_RATE.CURRENCY_DATE)
AND EXTRACT (YEAR FROM COST_SAVINGS.CREATION_DATE) = EXTRACT (YEAR FROM EXCHANGE_RATE.CURRENCY_DATE)
AND FINANCE_INVOICE.CURRENCY_CODE = EXCHANGE_RATE.CURRENCY_CODE) AS CREDIT_IN_USD
FROM COST_SAVINGS
LEFT JOIN FINANCE_INVOICE ON COST_SAVINGS.INVOICE_ID = FINANCE_INVOICE.INVOICE_ID
I feel like the issue may be with the third WHERE clause in my subquery (Trying to match the Currency codes). I'm not sure how resolve it though. Any thoughts?
Try putting LIMIT 1 in your subquery:
...RENCY_CODE = EXCHANGE_RATE.CURRENCY_CODE LIMIT 1) AS CREDIT_IN_USD
I believe your subquery is returning multiple rows. That doesn't work when you use a subquery in place of a column name in your SELECT clause.
If you don't want to use a subquery in place of a column name, try something like this. You'll join to a subquery generated virtual table.
Here's the virtual table for exchange rates. It uses GROUP BY to make one row (or no rows per month/year/currency code. If more than one row is in the raw table for any month/year/code, they get averaged with AVG(). You could also use MAX() or MIN().
SELECT AVG(CURRENCY_RATE) CURRENCY_RATE,
CURRENCY_CODE,
EXTRACT(MONTH FROM CURRENCY_DATE) MONTH,
EXTRACT(YEAR FROM CURRENCY_DATE) YEAR
FROM EXCHANGE_RATE
GROUP BY CURRENCY_CODE,
EXTRACT(MONTH FROM CURRENCY_DATE),
EXTRACT(YEAR FROM CURRENCY_DATE)
Try this and convince yourself it works.
Then build it into your overall query.
SELECT
COST_SAVINGS.COST_SAVINGS_ID,
COST_SAVINGS.whatever, ...
FINANCE_INVOICE.CURRENCY_CODE,
(COST_SAVINGS.ONE_TIME_CREDIT * RATE.CURRENCY_RATE) AS CREDIT_IN_USD
FROM COST_SAVINGS
LEFT JOIN FINANCE_INVOICE ON COST_SAVINGS.INVOICE_ID = FINANCE_INVOICE.INVOICE_ID
LEFT JOIN (SELECT AVG(CURRENCY_RATE) CURRENCY_RATE,
CURRENCY_CODE,
EXTRACT(MONTH FROM CURRENCY_DATE) MONTH,
EXTRACT(YEAR FROM CURRENCY_DATE) YEAR
FROM EXCHANGE_RATE
GROUP BY CURRENCY_CODE,
EXTRACT(MONTH FROM CURRENCY_DATE),
EXTRACT(YEAR FROM CURRENCY_DATE)
) RATE ON RATE.CURRENCY_CODE = FINANCE_INVOICE.CURRENCY_CODE
AND RATE.YEAR = EXTRACT(YEAR FROM COST_SAVINGS.CREATION_DATE)
AND RATE.MONTH = EXTRACT(MONTH FROM COST_SAVINGS.CREATION_DATE)

MySql, SELECT list is not in GROUP BY clause and contains nonaggregated column

I'm using MySql 5.7, and I'm getting an error in this query:
SELECT
COUNT(id) AS sales,
SUM(amount) AS total,
created
FROM
`payments`
WHERE status =1
GROUP BY MONTH(created);
if I change GROUP BY MONTH(created)
with:
GROUP BY created
then the error is gone. I dont have access to my.ini, to make changes to sql_mode.
Since you group month-wise, you shold output the months also
SELECT COUNT(id) AS sales,
SUM(amount) AS total,
MONTH(created)
FROM payments
WHERE status = 1
GROUP BY MONTH(created)
Otherwise MySQL has to pick a created value from the group. But you should define what to display.
Another possibility instead of outputting MONTH(created) would be a aggreagtion of the date like min(created) which would output the earliest date of each month.

SELECT and GROUP BY month efficiently

I have a column of type date. I want to group rows per month for a particular year.
I did the following:
SELECT SUM(price), DATE_FORMAT(production_date, '%Y%m')
FROM TABLE
WHERE YEAR(production_date) = ?
GROUP BY 2
Is there a better/more efficient way to do this?
Instead of specifying the year using the YEAR function
SELECT SUM(price), DATE_FORMAT(production_date, '%Y%m')
FROM TABLE
WHERE YEAR(production_date) = 2014
GROUP BY 2
specify it like this
SELECT SUM(price), DATE_FORMAT(production_date, '%Y%m')
FROM TABLE
WHERE production_date BETWEEN '2014-01-01' AND '2014-12-31'
GROUP BY 2
The 2nd query enables the db to use an index on production_date
you are almost there :)
SELECT SUM(price), MONTH(production_date)
FROM TABLE
WHERE YEAR(production_date) = ?
GROUP BY 2

What is the best way to select rows with maximum value?

I have come across a task, I managed to complete the objective but the solution I got is not optimum, I need more optimum solution. I have used normal Sub Queries May be Correlated Sub Query can solve this better.
This is the table i made
SELECT custid,
count(DISTINCT bid) AS Total
FROM loan
GROUP BY custid;
The output of this is like:-
What I want is the custid having maximum Total.
One way to do it is using Order by Total DESC LIMIT 1 but this will give only 1 result.
What I did is
SELECT custid
FROM (SELECT custid,
count(DISTINCT bid) AS Total
FROM loan
GROUP BY custid) c1
WHERE total = (SELECT max(Total)
FROM (SELECT custid,
count(DISTINCT bid) AS Total
FROM loan
GROUP BY custid) c2)
This gives me correct result that is
What I want to do is reduce the code, because here I am writing the same thing again. I know there must be a simpler way to do it. Maybe a correlated query.
Looking for some good answers. This is basically to clear my concepts only
Sorry, if it is noob question. I am a noob to SQL.
After understand what OP want with #Ravinder 's tip,
I guess build in mysql function GROUP_CONCAT is what you need, sql is:
select custid_count.Total, GROUP_CONCAT(custid_count.custid order by custid_count.custid asc SEPARATOR ',') as custids from
(select custid, count(distinct bid) as Total from loan group by custid order by Total desc) as custid_count
group by custid_count.Total
order by custid_count.Total desc
limit 1;
the result column custids is the max ids concated by ',' ,after the query, you need to split custids by ',' and convert each substring to number type you need,
Here is another way:
select * from loan
where custid =
(
select custid_count.custid from
(select custid, count(distinct bid) as Total from loan group by custid order by Total desc) as custid_count
order by custid_count.Total desc
limit 1
);
First find the custid with max count, then query all rows which match the custid,
I haven't tried this in mysql, but in the sql language I'm using it is fine to use a aggregation function without a group by so something like this
select custid, total, max(total) as maxtotal
from (select custid, count(distinct bid) as total
from loan
group by custid) c1;
would tag on every line both the individual customer total and the table wide max total, and you'd just have to filter on the ones that where the total was equal to the max total. That would give you a final answer of something like this:
select custid
from (select custid, count(distinct bid) as total
from loan
group by custid) c1
where total = max(total);

Mysql Nested query and GROUP BY

I am trying to perform the following query on my database :-
SELECT
source, Month as t1,
GROUP_CONCAT(SELECT SUM(amount) FROM `reports` GROUP BY Month) as amount
FROM `reports`
GROUP BY source
To get the source, month and the concatenated string of the sum of the money that is obtained by the distinct source in 1 month. But I get a syntax error.
I'm not exactly sure what you need, hopefully it is one of these two:
SELECT source, Month, SUM(amount) as sum
FROM reports
GROUP BY source, Month
The above, but grouped by source with the sums listed in one field:
SELECT source, GROUP_CONCAT(sum) as sums
FROM (
SELECT source, Month, SUM(amount) as sum
FROM reports
GROUP BY source, Month
) as t
GROUP BY source