I am trying to find a way of building a result set which is comprised a comparison of data from two specified years.
So it the result set would look something akin to this
PRODUCT - 2019 QTY - 2020 QTY
Car 10 10
Boat 10 0
Plane 0 10
You can use conditional aggregation. I am guessing something like this:
select product,
sum( year = 2019 ) as qty_2019,
sum( year = 2020 ) as qty_2020
from t
group by product;
This assumes that your raw data has one row per item you want to count.
If you need to sum quantity from a column then use:
select product,
sum( case when year = 2019 then quantity else 0 end ) as qty_2019,
sum( case when year = 2020 then quantity else 0 end ) as qty_2020
from t
group by product;
Related
I am quite new to SQL.
I want to count the number of records for February (or for all months) that are created in a table this year, if no records yet has not been created for the month i want to calculate last years count for the month.
The result should then change over the year, when we get to 1:st of April the result should show 0 records.
I tried to use a Case, it "works" when there is no new records for the current year, it will show number of records created last year for the month, but for example january we have records created, and the sum becomes the sum of this years records in January plus records from January last year.
I thought the Case When should exit when the first when is true.
Any suggestions?
My code here:
SELECT
COUNT(`user_activity`.`creation_date`) AS `ticket_count`
FROM
`user_activity`
WHERE
CASE
WHEN (Year(creation_date)=Year(curdate()) and MonthName(curdate())='January' is not null) >0
THEN ((MONTHNAME(`user_activity`.`creation_date`) = 'January') AND Year(`user_activity`.`creation_date`)=year(curdate())))
when(Year(creation_date)=Year(curdate())-1 and MonthName(curdate())='January' is not null) >0
then
((MONTHNAME(`user_activity`.`creation_date`) = 'January') AND (Year(`user_activity`.`creation_date`)=year(curdate())-1))
END;
One simple way to get your query is to run two queries that return one row for the respective year / month and apply a coalesce between them getting only the first counted value that HAS records. If nothing for this year, grab count from last year.
select
case when coalesce( thisYear.Recs, 0 ) = 0
then lastYear.Recs
else thisYear.Recs ) end Ticket_Count
from
( select count(*) Recs
from User_Activity
where creation_date >= '2022-02-01'
AND creation_date < '2022-03-01' ) lastYear
LEFT JOIN
( select count(*) Recs
from User_Activity
where creation_date >= '2023-02-01'
AND creation_date < '2023-03-01' ) thisYear
-- join always for principle, include joining "ON" clause
-- since both queries above always return 1 row, 1=1 works
on 1=1
In my warehouse project, I want to call mysql data and want to display record per month name as row wise.
Below is my mysql code
SELECT `Invoice_No`,
`WH_Name`,
SUM(`Balance`),
`Material_Issue_Date`
FROM `NEW_STOCK_TEMP`
and below is my current output
But I want to get output like below
Any suggestions to modify the code or what would be the best query to get output on same way?
thanks in advance for your support here.
Use case statement for every month of a year. If getting particular year data then use YEAR() or for few months then use between startdate and enddate. WH_name have been used in group by clause along with invoiceNo if same warehouse name for multiple invoices otherwise use MAX(WH_Name) in select clause and remove from group by clause.
-- MySQL
SELECT Invoice_No
,WH_Name
,SUM(CASE WHEN MONTH(Material_Issue_Date) = 1 THEN Balance END) jan
,SUM(CASE WHEN MONTH(Material_Issue_Date) = 2 THEN Balance END) feb
,SUM(CASE WHEN MONTH(Material_Issue_Date) = 3 THEN Balance END) mar
,SUM(CASE WHEN MONTH(Material_Issue_Date) = 4 THEN Balance END) apr
...
,SUM(CASE WHEN MONTH(Material_Issue_Date) = 12 THEN `Balance` END) dec
FROM NEW_STOCK_TEMP
WHERE YEAR(Material_Issue_Date) = 2021
GROUP BY Invoice_No
,WH_Name;
You can do something like this
SELECT `Invoice_No`,
`WH_Name`,
(SELECT SUM(`Balance`) FROM NEW_STOCK_TEMP where Material_Issue_Date='January') AS January, (SELECT SUM(`Balance`) FROM NEW_STOCK_TEMP where Material_Issue_Date='February') AS February
FROM `NEW_STOCK_TEMP`
I have a simple piece of SQL code where I am trying to get the monthly averages of numbers. But the problem I am running into is if any number within any given month is 0 then the average returned is 0 or if there are any rows that don't exist with any given month then there are no values returned at all for that month. Hopefully, someone can give me some insight as to what I am doing wrong.
GROUP BY 1 = a.metric and GROUP BY 2 = a.report_dt within the subquery
I have tried inserting the missing rows with a value of 0, but as I said it will return the averaged value as 0 as well.
SELECT a.report_dt - INTERVAL 1 DAY AS 'Date',
a.metric,
a.num
FROM (SELECT *
FROM reporting.tbl_bo_daily_levels b
WHERE b.report_dt = reporting.func_first_day(b.report_dt)
AND b.report_dt > DATE_SUB(NOW(), INTERVAL 12 MONTH)
GROUP BY 1,2
)a;
My expected results are to get the average numbers of each month even if there are non-existent rows within the specified date range or even if there zeroes as values.
You need a relation of all the months you want to span. This can be made ad hoc with UNION ALL. Then left join the data on the months GROUP BY the month and the metric and get avg(num).
SELECT m.year,
m.month,
l.metric,
coalesce(avg(l.num), 0)
FROM (SELECT 2017 year,
12 month
UNION ALL
SELECT 2018 year,
1 month
UNION ALL
SELECT 2018 year,
2 month
...
SELECT 2018 year,
11 month
UNION ALL
SELECT 2018 year,
12 month) months m
LEFT JOIN reporting.tbl_bo_daily_levels l
ON year(l.report_dt) = m.year
AND month(l.report_dt) = m.month;
GROUP BY m.year,
m.month,
l.metric;
(Change the second parameter to coalesce if you want any other number than 0 if there are no numbers for a month. Or don't use coalesce() at all if you want NULL in such cases.)
I am doing a SELECT from a MYSQL table
Table looks like this
year tour starts scoring_avg
1990 EUR 5 71.56
1990 USA 6 0.0
1991 EUR 12 71.21
1991 USA 8 69.23
I am doing a SELECT like so
SELECT
year,
SUM(starts),
SUM(starts*scoring_avg) as scoring.avg
FROM scores
GROUP BY year
Goal is to get combined scoring average for the year, combining the EUR and USA rows for each year.
After the SELECT, I divide scoring_avg by starts. Since I added a 6 to starts from the second line, with no scoring_avg for that line, the result is not correct.
Works fine for year 1991.
Doesn't work for year 1990, since the scoring_avg for the USA row is 0.
Is there a way the SELECT can be modified to only use the ps.starts*ps.scoring_avg in the SUM where ps.scoring_avg in that row is greater than 0?
Thank you.
-- Ed
If you just want to change scoringavg, use conditional aggregation:
SELECT year, SUM(starts),
SUM(case when scoring_avg > 0 then starts*scoring_avg end) as scoring_avg
FROM scores
GROUP BY year;
However, I would suggest doing all the work in a single query and not doing any division afterwards. The following calculates the average that you want:
SELECT year, SUM(starts),
(SUM(case when scoring_avg > 0 then starts*scoring_avg end) /
SUM(scoring_avg > 0)
) as scoring_avg
FROM scores
GROUP BY year;
You may try this:
SELECT
year,
SUM(starts),
SUM(starts*scoring_avg) as scoring.avg
FROM scores
WHERE scoring_avg > 0
GROUP BY year
You could use an expression that conditionally returns either the value from the starts column, or 0 (or NULL), based on the value in the scoring_avg column. As an example:
IF(scoring_avg=0,0,starts)
That says, if scoring_avg has a value of zero (for a particular row), then return zero; otherwise, returns the value from the starts column. This is MySQL specific syntax, equivalent to the an ANSI-standard CASE expression:
CASE scoring_avg WHEN 0 THEN 0 ELSE starts END
In the context of your query:
SELECT s.year
, SUM( IF(s.scoring_avg=0,0,s.starts) ) AS `starts`
, SUM( s.starts*s.scoring_avg ) AS `scoring.avg`
, SUM( s.starts*s.scoring_avg ) /
SUM( IF(s.scoring_avg=0,0,s.starts) ) AS `scoring.avg_div_starts`
FROM scores s
GROUP BY s.year
I have a table with emp_id, income, etc.
I wish to get number of records for a query like
select * from table_name where income <= 500;
There will be at least 3 such income groups - which will b given at report generation time.
Further I wish to get all 3 Counts - and group the results by the count of their respective income group - all this in a single query.
What is the easiest way to do this?
Can you try this ,if this doesn't suite your need you may need to write a custom stored procedure
SELECT
sum((income <= 500)) as range1,
sum((income <= 1000)) as range2
FROM table_name
sample fiddle
You can use a CASE expression to create your categories, and then a GROUP BY to summarize the categories.
SELECT COUNT(*) AS num,
CASE WHEN income IS NULL THEN 'missing'
WHEN income <= 0 THEN '0'
WHEN income <= 500 THEN '1 - 500'
WHEN income <= 1000 THEN '501-1000'
ELSE '> 1000'
END AS category
FROM table_name
GROUP BY category WITH ROLLUP
Including the WITH ROLLUP clause will give you an overall count as well as the count of each category.