How to total "AS" column in mysql query? - mysql

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.

Related

I was wondering if anyone knew how to find the min value and a max value and find the timeframe between them?

im working with a movie database I made and I wanted to make a select query that would separately select the the movie with the highest revenue and the movie with the lowest value and find the timeframe between them
i've tried to use the min and max functions to try to separately select the lowest and the highest movies and tried to use datediff() to try and the timeframe between them. my code is below
SELECT titles.title, min(financial_info.revenue),max(financial_info.revenue),
DATEDIFF(year, date(min(financial_info.revenue), date(max(financial.revenue)))
production_company.release_date
from titles
left join financial_info on titles.id = financial_info.id
left join production_company on
titles.imdb_id = production_company.imdb_id
I had aggregation error and a syntax error
The general format for this kind of query would be:
SELECT stuff
, maxB.Y - minB.Y -- Or, in this case DATEDIFF instead of minus
FROM (SELECT MIN(x) AS minX, MAX(x) AS maxX FROM a) AS minMax
INNER JOIN a AS minA ON minMax.minX = minA.X
INNER JOIN a AS maxA ON minMax.maxX = maxA.X
INNER JOIN b AS minB ON minA.b_id = minB.b_id
INNER JOIN b AS maxB ON maxA.b_id = maxB.b_id
;
You can end up with more than one result if there are multiple entries with the same revenue amount. (2 at min revenue and 3 at max revenue would yield 6 results).

How to show last data (max data) of each group by on mysql

I have query like below:
SELECT kd.id_karir, kd.nama, kd.kelamin,
(YEAR(NOW())-YEAR(tanggal)) usia, MAX(pf.jenis), pf.jenis,
pf.nama AS pendidikan, pf.jurusan, kd.alamat, kd.telepon,
kd.handphone, kd.email, kd.tempat AS tempat_lahir,
kd.tanggal AS tanggal_lahir
FROM keadaan_diri AS kd
LEFT OUTER JOIN pendidikan_formal AS pf ON (kd.id_karir = pf.id_karir)
WHERE kd.id_karir = 'P1409047'
GROUP BY kd.id_karir
ORDER BY kd.nama ASC, pf.jenis DESC
I mean to returning the last data on the table pendidikan_formal using max and group but the query doesn't work.
First of all, you can / should (depending on the MySQL configuration) only select and order by columns that are part of your group by clause. For all other columns, you have to specify an aggregation function. For example, let's say you have two records of humans, both have the same name and a different age. When you group by name, you have to choose one of the two age values (max, min, average, ...). If you don't care which, you could turn off sql mode only full group by. I wouldn't suggest that however.
In order to get the one record with some maximum value however, group by is not the right approach. Take a look at these examples:
Subselect:
SELECT name, age, ...
FROM humans
WHERE age=(SELECT MAX(age) FROM humans);
Order by and limit:
SELECT name, age, ...
FROM humans
ORDER BY age DESC
LIMIT 1;
Left join:
SELECT name, age, ...
FROM humans h1
LEFT JOIN humans h2 ON h1.age < h2.age
WHERE h2.age IS NULL;
Now if you want all maximum rows per group, check one of these answers with tag greatest-n-per-group.
You can use a correlated subquery. Your question is a bit vague; I assume that id_karir is the group and tanggal is the date.
If I understand correctly, this would apply to your query as:
SELECT kd.id_karir, kd.nama, kd.kelamin,
(YEAR(NOW())-YEAR(tanggal)) usia, pf.jenis, pf.jenis,
pf.nama AS pendidikan, pf.jurusan, kd.alamat, kd.telepon,
kd.handphone, kd.email, kd.tempat AS tempat_lahir,
kd.tanggal AS tanggal_lahir
FROM keadaan_diri kd LEFT OUTER JOIN
pendidikan_formal pf
ON kd.id_karir = pf.id_karir AND
pf.tanggal = (SELECT MAX(pf2.tanggal) FROM pendidikan_formal pf2 WHERE pf2.id_karir = pf.id_karir)
This is not an aggregation query. This is a filtering query.

Rewrite MySQL code to retrieve average time

I don't know if that's a question for SO, if not please delete it. I am using the query below to calculate an average time it takes for a ticket on our service desk to get closed.
I don't have write permissions on the database, so I can't create functions, variables etc.
I strongly believe that there must be a better/nicer, more robust way to calculate that, than my query below, any thoughts?
What I want to avoid, if possible, is to recalculate the count value, which especially with all the where clauses makes the query a bit slow.
SELECT Count(hd_ticket.id) AS 'Tickets #',
ROUND(( Timestampdiff(hour, hd_ticket.created, hd_ticket.time_closed) /
(SELECT Count(hd_ticket.id)
FROM
hd_ticket
LEFT JOIN hd_status
ON hd_status_id = hd_status.id
WHERE
Month(
hd_ticket.time_closed) = 12
AND
Year
(hd_ticket.time_closed) = 2017
AND
hd_status.state LIKE '%close%'
AND
hd_ticket.hd_queue_id IN ( 8 )) )) AS
'AVG Closure Time'
FROM hd_ticket
LEFT JOIN hd_status
ON hd_status_id = hd_status.id
WHERE Month(hd_ticket.time_closed) = 12
AND Year(hd_ticket.time_closed) = 2017
AND hd_status.state LIKE '%close%'
AND hd_ticket.hd_queue_id IN ( 8 )
In a nutshell what the above query does is
SELECT COUNT(TICKETS) as 'Tickets #',
ROUND(TOTAL_TIME_TAKES_TO_CLOSE_TICKETS/COUNT(TICKETS + FILTERS)) as 'AVG Closure Time'
FROM HD_TICKET
SOME FILTERS
I would recommend:
SELECT Count(*) as Num_Tickets_Closed,
AVG( ( Timestampdiff(hour, t.created, t.time_closed) ) as AVG_CLosure_Time
FROM hd_ticket t LEFT JOIN
hd_status s
ON t.hd_status_id = s.id
WHERE t.time_closed >= '2017-12-01' AND
t.time_closed < '2018-01-01' AND
s.state LIKE '%close%' AND
t.hd_queue_id IN ( 8 ) ;
Notes:
First, you can just use AVG(). That greatly simplifies the query.
The date comparisons are made without functions. Although this likely has little impact in your case, it allows the use of indexes.
The names of the columns no longer have special characters, so they don't need to be escaped.
Table aliases make the query easier to write and to read.

Rewrite query with only 1 group by clause

This bellow query will result the post wise sum of like
SELECT
tblPost.Post,
SUM(tblPost.LikeCount),
CASE WHEN tblPost.Time
BETWEEN (SELECT
CONVERT(VARCHAR(10),
DATEADD(DD,DATEDIFF(DD 0,GETDATE()),-60),120)) AND CONVERT(date,GETUTCDATE())
THEN 'Last 60 Days'
ELSE 'More Than 1 Year'
END AS"date type"
FROM tblPost
INNER JOIN tblProfile ON (tblProfile.ID=tblPost.UID)
INNER JOIN tblWatchList ON (tblWatchList.ID=tblProfile.UID)
WHERE dbo.tblPost.Time BETWEEN (SELECT
CONVERT(VARCHAR(10),
DATEADD(DD,DATEDIFF(DD,0,GETDATE()), -60),120))AND CONVERT(date,GETUTCDATE())
GROUP BY tblPost.Post,tblPost.Time
This is my query and it is working fine but I want to rewrite this. How can I describe it here... in my query I am having two GROUP BY clauses (tblPost.Post,tblPost.Time) and exactly here I'm getting a problem. I want to rewrite this query such as a way that I can group my result only by tblPost.Post
Please help me.
Your WHERE clause already eliminates the two options you've presented for tblPost.Time - you explicitly state you're only ever going to retrieve "Last 60 days" so why are you bothering to have a whole CASE statement in the query?
And you're joining tables that aren't even represented. So start by cleaning your query up, use some aliases, and drop what you don't need:
SELECT P.Post, SUM(P.LikeCount)
FROM dbo.tblPost P
WHERE P.Time BETWEEN (SELECT CONVERT(VARCHAR(10), DATEADD(DD,DATEDIFF(DD,0,GETDATE()), -60),120)) AND CONVERT(date, GETUTCDATE())
GROUP BY P.Post

SQL SUM() in a month on month report

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