SQL SUM() in a month on month report - sql-server-2008

I have the following that returns the total invoiced amount for a given type of job. I now want to break it down into monthly totals. Any tips on how I should approach this
SELECT dbo.jm_job_type.job_type_desc, SUM(dbo.jm_invoice.invoice_amount) AS 'inv tot'
FROM dbo.jm_invoice INNER JOIN
dbo.jm_job ON dbo.jm_invoice.job_no = dbo.jm_job.job_no INNER JOIN
dbo.jm_job_type ON dbo.jm_job.job_type_no = dbo.jm_job_type.job_type_no
GROUP BY dbo.jm_job_type.job_type_desc

"floor" to the Month (most efficient way to get month+year only) and then GROUP BY that"
GROUP BY DATEADD(month,DATEDIFF(month,0, dbo.jm_invoice.YourDate),0)
so it would be:
SELECT dbo.jm_job_type.job_type_desc,
DATEADD(month,DATEDIFF(month,0, dbo.jm_invoice.YourDate),0) AS MonthYear,
SUM(dbo.jm_invoice.invoice_amount) AS 'inv tot'
FROM dbo.jm_invoice INNER JOIN
dbo.jm_job ON dbo.jm_invoice.job_no = dbo.jm_job.job_no INNER JOIN
dbo.jm_job_type ON dbo.jm_job.job_type_no = dbo.jm_job_type.job_type_no
GROUP BY dbo.jm_job_type.job_type_desc,
DATEADD(month,DATEDIFF(month,0, dbo.jm_invoice.YourDate),0)

Use the SQL Server datepart function on the date in question in your Group By like this:
GROUP BY
DatePart(yy, dbo.jm_invoice.some_date),
DatePart(mm, dbo.jm_invoice.some_date),
dbo.jm_job_type.job_type_desc

Add the year and month field to your SELECT list, and also add it to your GROUP BY list

Related

MySQL Error: 1111 (Invalid use of group function) [duplicate]

This question already has an answer here:
ERROR 1111 (HY000): Invalid use of group function
(1 answer)
Closed 1 year ago.
I'm not yet good at MySQL. Please check my sql below and help me understand where I went wrong with it. All I need is just one record for the order.id and the returned record must be the one whose shipped date is the latest.
Database error: Invalid SQL: SELECT orders.id, orders.customer_fk FROM orders INNER JOIN order_details ON order_details.order_fk=orders.id WHERE orders.payment_method IN ('AS','AC') AND ((orders.order_status='SHP' AND order_details.item_status='SHP' AND MAX(order_details.shipped_date) <= '2021-08-07') OR (orders.order_status='CAN' AND orders.order_date <= '2021-08-07 09:56:18')) AND orders.pii_status <> '1'GROUP BY orders.id
MySQL Error: 1111 (Invalid use of group function)
Instead of using MAX alone try to use a subselect
If you don't want the mad for every order.id then you need to add a inner join
SELECT
orders.id, orders.customer_fk
FROM
orders
INNER JOIN
order_details ON order_details.order_fk = orders.id
WHERE
orders.payment_method IN ('AS' , 'AC')
AND ((orders.order_status = 'SHP'
AND order_details.item_status = 'SHP'
AND (SELECT MAX(shipped_date) FROM order_details WHERE order_fk = orders.id) <= '2021-08-07')
OR (orders.order_status = 'CAN'
AND orders.order_date <= '2021-08-07 09:56:18'))
AND orders.pii_status <> '1'
GROUP BY orders.id
To explain it somewhat further
SELECT MAX(shipped_date) FROM order_details WHERE order_fk = orders.id) <= '2021-08-07'
Return true or false for every Order.id as it checks for every row in the outer select what the maximum date is and then checks it against the date.
After selecting all rows you GROUP BY(which i still don't get as you have no aggregation function it) comes for every order.id.
Maybe you should try a DISTINCT
You select both orders.id and orders.customer_fk, but you group by orders.id only. When using group by in SQL, all other columns not present in the group by clause must be aggregate functions, since for example in this current case you group the results by the order id, meaning there can be only one row per unique order id among the results.
And something has to happen with the list of values of the other column that all belong to this one grouped order id, this is where the aggregations come in. If it is a number you can calculate the MIN/MAX/AVG etc. of these, but the simplest aggregate is to just count the matching results.
So if you wanted your query to return the number of order.customer_fk for each unique order.id, just add SELECT orders.id, COUNT(orders.customer_fk).
Otherwise, if you didn't intend to group your results, you can remove the GROUP BY clause, or replace it with an ORDER BY.
If you want to filter using aggregation functions use having. However, I'm guessing that you just want to filter by the date:
SELECT o.id, o.customer_fk
FROM orders o INNER JOIN
order_details od
ON od.order_fk= o.id
WHERE o.payment_method IN ('AS','AC') AND
((o.order_status = 'SHP' AND od.item_status='SHP' AND od.shipped_date <= '2021-08-07') OR
(o.order_status = 'CAN' AND o.order_date <= '2021-08-07 09:56:18')
) AND
o.pii_status <> '1'
GROUP BY o.id

How to create a SQL ordering based on JOIN values and on today month

I have two databases
TABLE_ORDERS with id,created,user_id.....status_id
TABLE_STATUSES with it,title,ordering,month
ordering is an integer for ordering statuses and month is the month number (01-January, 02-February, ...)
I would like to create somethig like:
SELECT *
FROM TABLE_ORDERS,
TABLE_STATUSES
WHERE 1
AND TABLE_STATUSES.month >= '7'
ORDER BY TABLE_STATUSES.ordering
What should be the right syntax?
The wished result is a table of orders ordered by statues like "To be delivered on January, To be delivered on February" that will change automatically month by month.
Thank you for your support!
I think you should try
Select * from TABLE_ORDERS o inner join TABLE _STATUSES s ON o.id=s.id WHERE MONTH(s.month)>=7 ORDER BY s.ordering.
You can filter out months gretter than 7.
Good luck.
your query can go like this :
SELECT TABLE_ORDERS.*, TABLE_STATUSES.month
FROM TABLE_ORDERS INNER JOIN TABLE_STATUSES
ON TABLE_STATUSES.id = TABLE_ORDERS.status_id
ORDER BY TABLE_STATUSES.ordering
An example can be :
SELECT column_list
FROM table_1
INNER JOIN table_2 ON table_1.columnname = table_2.columnname;

How to total "AS" column in mysql query?

I need SUM of AS column "profit"and "purch_price". I tried few things group by stock.id etc but it is not giving me same answer. please let me know how to take their sum.
SELECT
jobc_consumble.Stock_id,
jobc_consumble.issued_qty,
jobc_consumble.total,
p_purch_stock.Price,
p_purch_stock.Price * jobc_consumble.issued_qty AS "purch_price",
jobc_consumble.total -(SELECT purch_price) AS "profit"
FROM
jobc_consumble
INNER JOIN p_purch_stock ON jobc_consumble.stock_id = p_purch_stock.stock_id
WHERE
DATE_FORMAT(
jobc_consumble.issue_time,
'%Y-%m-%d'
) BETWEEN '2018-07-03' AND '2018-07-03'
Output should be like so :
I want sum of last two columns.
sum of PROFIT: 1105
sum of purch_price: 11000
Just repeat the logic in your SELECT clause:
SELECT
j.Stock_id,
j.issued_qty,
j.total,
p.Price,
p.Price * j.issued_qty AS purch_price,
j.total - (p.Price * j.issued_qty) AS profit
FROM jobc_consumble j
INNER JOIN p_purch_stock p
ON j.stock_id = p.stock_id
WHERE
DATE_FORMAT(j.issue_time, '%Y-%m-%d') = '2018-07-03';
For some notes, the only alternative to repeating the purchase price logic would be to wrap your current query as a subquery and reuse the alias. But, that would probably not be too performant. Your DATE_FORMAT expression does not make much sense, because the range is just a single day. If you don't like my version, then let us know what logic you really intended.

Inner Join in ON statement

I am working on an assignment:
Compare the average daily revenue (as I define it in Teradata Week 5
Exercise Guide) of the store with the highest msa_income and the store
with the lowest median msa_income (according to the msa_income field).
In what city and state were these two stores, and which store had a
higher average daily revenue?
... and the answer key has a inner join in ON statement, which confused me a lot. I have only learnt Join in FROM. So I searched online about an inner join in ON statement, there was not much about it.
I am a new learner, so this question might be really basic. Thanks in advance for your patience!
The line I where I had a problem is: ON m.store=t.store JOIN strinfo s
SELECT SUM(store_rev. tot_sales)
SUM(store_rev.numdays) AS daily_average,
store_rev.msa_income as med_income,
store_rev.city, store_rev.state
FROM (SELECT COUNT (DISTINCT t.saledate) as numdays,
EXTRACT(YEAR from t.saledate) as s_year,
EXTRACT(MONTH from t.saledate) as s_month, t.store,
sum(t.amt) as tot_sales,
CASE
when extract(year from t.saledate) = 2005 AND extract(month from t.saledate) = 8 then 'exclude'
END as exclude_flag, m.msa_income, s.city, s.state
FROM trnsact t JOIN store_msa m
ON m.store=t.store JOIN strinfo s
ON t.store=s.store
WHERE t.stype = 'P' AND exclude_flag IS NULL
GROUP BY s_year, s_month, t.store, m.msa_income, s.city, s.state
HAVING numdays >= 20) as store_rev
WHERE store_rev.msa_income IN ((SELECT MAX(msa_income)
FROM store_msa),(SELECT MIN(msa_income) FROM store_msa))
GROUP BY med_income, store_rev.city, store_rev.state;
Perhaps it would be easier to follow if written like this:
FROM trnsact t JOIN
store_msa m
ON m.store = t.store JOIN
strinfo s
ON t.store = s.store
The JOIN isn't in the ON statement. The FROM clause consists of multiple joins, chained together.
You can think of the JOIN keyword as ending the ON clause and starting a new join condition.

join table and filter and take aggregrate function sql access

Is it possible to join two tables,filter the data and take aggregate function in MS access? I have two tables
Inv_details:invnum,itmcde,qnt,price
Inv_summary:invnum,date,total
I need to join this tables and filter them with date range and have sum of qnt and price order by itmcde.
I tried something like this.
SELECT inv.itmcde,SUM(inv.qnt),SUM(inv.price) FROM (SELECT inv_s.invnum,inv_s.date,inv_d.itmcde,inv_d.total FROM Inv_summary as inv_s INNER JOIN Invoice_details as inv_d ON inv_d.invnum =inv_s.invNum WHERE inv_s.date BETWEEN #3/4/2013# And #5/16/2013# ) as inv ORDER BY inv.itmcde
But this is not working.
Try
SELECT d.itmcde,
SUM(d.qnt) AS qnt,
SUM(d.price) AS price
FROM Inv_summary s INNER JOIN Inv_details d
ON d.invnum = s.invnum
WHERE s.date BETWEEN #3/4/2013# AND #5/16/2013#
GROUP BY d.itmcde
ORDER BY d.itmcde
SQLFiddle Although this fiddle is for SQL Server same general rules should apply in MS Access