I am using a hosted SQL 2008 database (so can't create tables or modify values) and would like to divide two numbers from the same column to get a single percentage answer. The values are entered into the same column (TA_ANS_ANSWER) but the value entered is based on another field, the question (TA_ANS_QUESTION).
e.g. for this month;
First question - "Total No. Contractors on e-learning User List" - Answer entered '430'.
Second question - "Total No. Contractors on e-learning inducted report" - Answer entered '357'
I need to get the value 83% for the above.
I need to calculate a single percentage value for each Month as the answers get populated.
The query below gives the base query which returns the name of the previous MONTH (e.g. Nov), PPM ID and Answer (e.g. 430). I can modify this to return both rows, 1 for each question answered but I only want a single row with the Month, PPM ID and Percentage calculation.
Apologies if the answer is staring me in the face but any help would be greatly appreciated.
SELECT CONVERT(varchar(3), TA_DUE_DATE-28, 100) AS MONTH,
TA_TASK_ID AS PPM,
F_TASK_ANS.TA_ANS_ANSWER AS ANSWER
FROM F_TASK_ANS
INNER JOIN F_TASKS
ON F_TASK_ANS.TA_ANS_FKEY_TA_SEQ = F_TASKS.TA_SEQ
WHERE TA_ANS_ANSWER <> ''
AND F_TASKS.TA_FKEY_CTR_SEQ = 126
AND F_TASK_ANS.TA_ANS_QUESTION LIKE '%Total No. Contractors on e-learning User List%'
AND (TA_HIST_STATUS IS NULL OR TA_HIST_STATUS = 'COMPLETE')
AND TA_TASK_ID LIKE '%6025'
AND TA_DUE_DATE >= GETDATE()-360
AND TA_DUE_DATE <= GETDATE()+7
ORDER BY PPM
What you are looking for is called a pivot. This can be done with the PIVOT keyword, or it can be done manually with GROUP BY and MIN(CASE WHEN ... END). Check out other answers tagged with "pivot" for more examples.
SELECT CONVERT(varchar(3), TA_DUE_DATE-28, 100) AS MONTH,
TA_TASK_ID AS PPM,
MIN(CASE WHEN F_TASK_ANS.TA_ANS_QUESTION LIKE '%Total No. Contractors on e-learning inducted report%' THEN F_TASK_ANS.TA_ANS_ANSWER END) +0.0
/ MIN(CASE WHEN F_TASK_ANS.TA_ANS_QUESTION LIKE '%Total No. Contractors on e-learning User List%' THEN F_TASK_ANS.TA_ANS_ANSWER END)
AS PERCENTAGE
FROM F_TASK_ANS
INNER JOIN F_TASKS
ON F_TASK_ANS.TA_ANS_FKEY_TA_SEQ = F_TASKS.TA_SEQ
WHERE TA_ANS_ANSWER <> ''
AND F_TASKS.TA_FKEY_CTR_SEQ = 126
AND (F_TASK_ANS.TA_ANS_QUESTION LIKE '%Total No. Contractors on e-learning User List%' OR
(F_TASK_ANS.TA_ANS_QUESTION LIKE '%Total No. Contractors on e-learning inducted report%')
AND (TA_HIST_STATUS IS NULL OR TA_HIST_STATUS = 'COMPLETE')
AND TA_TASK_ID LIKE '%6025'
AND TA_DUE_DATE >= GETDATE()-360
AND TA_DUE_DATE <= GETDATE()+7
GROUP BY CONVERT(varchar(3), TA_DUE_DATE-28, 100),TA_TASK_ID
One possible answer is to use a Common Table Expression (CTE). Something like this:
;with TotalOnELearningList (Month, TaskID, NumberOnList) as
(
select
convert(varchar(3), ta_due_date - 28, 100) as month,
ta_task_id,
f_task_ans.ta_ans_answer
from ...
),
TotalOnInductedReport (Month, TaskID, NumberInductedReport) as
(
...
),
select
case NumberInductedReport when 0 then 0 else NumberOnList / NumberInductedReport * 100 end as 'Percent',
...
from TotalOnELearningList
inner join TotalOnIndutedReport
on...
Related
I am working on a simple query trying to display the total of the totals for 12 periods. I am using a SUM(SUM(value)) function to retrieve the data that I want, however, I am having a hard time displaying a second column in my result.
SELECT CENTRE, SUM(SUM(AMOUNT)) "TOTAL PAY" FROM AB
WHERE ACCOUNT LIKE 'N%' AND CENTRE = '2001' AND YEAR > 2015 GROUP BY AMOUNT, CENTRE;
The error that I am getting has to do with the grouping of the sentence.
Can you please tell me what I have done wrong. I have solved the problem with a sub-query, but I need to fix this query as well because it is used in a more advanced one as a sub-query.
Your questions is too vague to know for sure what you want. For example, what do you mean by "totals for 12 periods"? Is it that for YEAR > 2015 you have 12 rows? Are you always having CENTRE = in your WHERE clause? If so, this might be what you want:
SELECT
MAX(centre) "CENTRE",
SUM(amount) "TOTAL PAY"
FROM
ab
WHERE
account LIKE 'N%'
AND
centre = '2001'
AND
year > 2015;
Or in case CENTRE = 'smth' might not be in your WHERE clause an you need total values for each CENTRE:
SELECT
centre "CENTRE",
SUM(amount) "TOTAL PAY"
FROM
ab
WHERE
account LIKE 'N%'
/* AND
centre = '2001'*/
AND
year > 2015
GROUP BY
centre;
Or in case for every (or one) CENTRE row you need to have total value of all centres:
SELECT
"CENTRE",
total "TOTAL PAY"
FROM
(
SELECT
centre,
ROW_NUMBER() OVER(PARTITION BY
centre
ORDER BY
0
) rn,
SUM(
amount
) OVER(PARTITION BY
0
) total
FROM
ab
WHERE
account LIKE 'N%'
AND
year > 2015
)
WHERE
rn = 1;
I need to drill into detail on to an existing report which shows me the total profitability per customer, per month on a telecoms company.
The company sells calls, service charges and has discounts.
This is the query that I'm using, using one customer in particular:
SELECT
custumer_name,
ISNULL(SUM(CASE CONVERT(VARCHAR(10), month_end, 103)
WHEN '31/10/2016'
THEN totcall + isnull(totrec, 0) - discount
ELSE 0
END), 0) AS '31/10/2016',
SUM(totcall) AS 'Total Calls',
SUM(totrec) AS 'Total Rec',
SUM(discount) AS 'Discounts'
FROM
total_sales
INNER JOIN
customer_details ON billingaddress = customer_details .siteid
INNER JOIN
sales_month d ON total_sales.periodid = d.monthid
INNER JOIN
customer b ON customer_details .id = b.id AND b.is_customer = 1
WHERE
b.custumer_name = '2
GROUP BY
b.custumer_name
ORDER BY
b.custumer_name ASC
This is bringing back the correct total however when I need to show the drilldown of the total on calls, rec & discounts it is showing me the actual sum of every months' data which is stored on that table.
I'm not sure how can I get the last 3 columns to itemise the total without specifying the actual month (as the report has columns for the last 12 months of data.
Please help?
Thank you!
PS. The DB is a SQL Server 2008
First, I apologize if this has been answered elsewhere, but I was unable to find anything today. If it has been answered, the lack is me, not the search system.
I am having an issue where in a stored procedure works fairly quickly until I get to a specific point.
I have a database of POS sales data for a restaurant chain.
Among the various tables we have, the ones I need for this query are:
Item (the definitions of the various items; each row includes the SALES category the item belongs to; see caveats below)
Category (the definitions of the various categories items can be in)
CategoryItem (the mapping between the above)
HstItem (the historical sales of the items)
Caveats: There are 2 types of categories each item can be in:
sales categories: each item can be in one sales category at a time.
reporting categories: each item can be in a arbitrary number of these categories simultaneously.
I am needing to get sales totals for 6 date ranges for a specific REPORTING category (week to date, wtd ly, period to date, ptd ly, year to date, ytd ly).
All of that said, for all of my code the query / procedure runs in a decent amount of time, until to the section for the reporting category.
My select statement currently includes the following WHERE clause:
where hstitem.itemid in (select fkitemid from categoryitem where categoryitemid = ##)
I am looking for a more efficient / faster way to execute this.
Any assistance is greatly appreciated. Thanks in advance.
EDIT:
The full original query is as follows:
insert into #GnG (GStoreID, CurWkGNG, CurWkGNGLY,CurYTDGNG,CurYTDGNGLY,CurrPTDGNG,CurrPTDGNGLY)
select
hgi.FKStoreId,
CurWkGnG = sum(case when hgi.DateOfBusiness between #SDate and #EDate then hgi.price else 0 end),
CurWkGnGLY = sum(case when hgi.DateOfBusiness between #SDateLY and #EDateLY then hgi.price else 0 end),
CurYTDGnG =
case
when convert(varchar(10),opendate,126) between convert(varchar(10),#LYTDStart,126) and convert(varchar(10),#LYTDEnd,126) then sum(case when hgi.DateOfBusiness between DATEADD(day, (DATEPART(week, opendate) * 7 + DATEPART(weekday, opendate)) - (DATEPART(week, DATEADD(year, 1, opendate)) * 7 + DATEPART(weekday, DATEADD(year, 1, opendate))), DATEADD(year, 1, opendate)) and #CYTDEnd then hgi.price else 0 end)
else sum(case when hgi.DateOfBusiness between #CYTDStart and #CYTDEnd then hgi.price else 0 end)
end,
CurYTDGnGLY = sum(case when hgi.DateOfBusiness between #LYTDStart and #LYTDEnd then hgi.price else 0 end),
CurrPTDGnG = sum(case when hgi.DateOfBusiness between #CurrPtDStart and #CurrPtDEnd then hgi.price else 0 end),
CurrPTDGnGLY = sum(case when hgi.DateOfBusiness between #CurrPtDLYStart and #CurrPtDlyEnd then hgi.price else 0 end)
from hstGndItem hgi
join #StoresIncluded si
on hgi.FKStoreID = si.StoreID
where hgi.fkitemid in
(select fkitemid from categoryitem where categoryitemid = 25)
group by hgi.fkstoreid, opendate, comping
order by hgi.fkstoreid
Try converting the "IN" to a inner join like so :
FROM hstitem h inner join categoryitem c on c.fkitemid = h.itemid
where c.categoryitemid = ##
You can use WHERE EXISTS instead of IN to check if the ID exists in the table:
WHERE EXISTS
(
SELECT ci.fkitemid
FROM categoryitem ci
WHERE ci.categoryitemid = ## AND ci.fkitemid = hstitem.itemid
)
The difference between the IN clause and using EXISTS is that the sub-query inside the WHERE EXISTS will exit prematurely after a match have been found while the IN clause would wait until the sub-query is finished.
I apologize for the lag in my response here.
I found AN answer. Dont know if it is the right one or not, but it works for us.
I removed the code to use a sub select from the where, and am now generating a new table to hold the values that should pull. The new code to populate the table runs each morning around 0600. I then am having the main code simply join to that table to pull the single answer, rather than perform math based on the sub-query.
Thank you all for the suggestions.
I am trying to run a query on an Oracle 10g DB to try and view 2 groups of transactions. I want to view basically anyone who has a transaction this year (2014) that also had a transaction in the previous 5 years. I then want to run a query for anyone who has a transaction this year (2014) that hasn't ordered from us in the last 5 years. I assumed I could do this with the 'IN' and 'NOT IN' features. The 'IN' query runs fine but the 'NOT IN' never completes. DB is fairly large which is probably why. Would love any suggestions from the experts!
*Notes, [TEXT] is a description of our Customer's Company name, sometimes the accounting department didn't tie this to our customer ID which left NULL values, so using TEXT as my primary grouping seemed to work although the name is obscure. CODE_D is a product line just to bring context to the name.
Below is my code:
SELECT CODE_D, sum(coalesce(credit_amount, 0) - coalesce(debet_amount,0)) as TOTAL
FROM
gen_led_voucher_row_tab
WHERE ACCOUNTING_YEAR like '2014'
and TEXT NOT IN
(select TEXT
from gen_led_voucher_row_tab
and voucher_date >= '01-JUN-09'
and voucher_date < '01-JUN-14'
and (credit_amount > '1' or debet_amount > '1')
)
GROUP BY CODE_D
ORDER BY TOTAL DESC
Try using a LEFT JOIN instead of NOT IN:
SELECT t1.CODE_D, sum(coalesce(t1.credit_amount, 0) - coalesce(t1.debet_amount,0)) as TOTAL
FROM gen_led_voucher_row_tab AS t1
LEFT JOIN gen_led_voucher_row_tab AS t2
ON t1.TEXT = t2.TEXT
AND t2.voucher_date >= '01-JUN-09'
AND t2.voucher_date < '01-JUN-14'
AND (credit_amount > '1' or debet_amount > '1')
WHERE t2.TEXT IS NULL
AND t1.ACCOUNTING_YEAR = '2014'
GROUP BY CODE_D
ORDER BY TOTAL DESC
ALso, make sure you have an index on the TEXT column.
You can increase your performance by changing the Not In clause to a Where Not Exists like as follows:
Where Not Exists
(
Select 1
From gen_led_voucher_row_tab b
Where voucher_date >= '01-JUN-09'
and voucher_date < '01-JUN-14'
and (credit_amount > '1' or debet_amount > '1')
And a.Text = b.Text
)
You'll need to alias the first table as well to a for this to work. Essentially, you're pulling back a ton of data to just discard it. Exists invokes a Semi Join which does not pull back any data at all, so you should see significant improvement.
Edit
Your query, as of the current update to the question should be this:
SELECT CODE_D,
sum(coalesce(credit_amount, 0) - coalesce(debet_amount,0)) as TOTAL
FROM gen_led_voucher_row_tab a
Where ACCOUNTING_YEAR like '2014'
And Not Exists
(
Select 1
From gen_led_voucher_row_tab b
Where voucher_date >= '01-JUN-09'
and voucher_date < '01-JUN-14'
and (credit_amount > '1' or debet_amount > '1')
And a.Text = b.Text
)
GROUP BY CODE_D
ORDER BY TOTAL DESC
i have a view as below.
SELECT TOP (100) PERCENT 'SA' AS Doc_Type1, 'A' + SUBSTRING('000000', 1, 6 - LEN(CAST(dbo.companies.companyId AS varchar(10))))
+ CAST(dbo.companies.companyId AS varchar(10)) AS Client_ID, 1200 AS Bank_Nom, 0 AS Department, CONVERT(nvarchar(20),
dbo.invoices.invoiceDatePaid, 103) AS Cleared_Date, 'Bacs' AS Payment_type, dbo.invoices.invoiceId, dbo.invoices.invoiceTotal AS Value, '9' AS vat,
' ' AS bllank, 1 AS Ex_rate
FROM dbo.invoices INNER JOIN
dbo.companies ON dbo.invoices.invoiceCompanyId = dbo.companies.companyId
WHERE (dbo.invoices.invoiceDatePaid >= DATEDIFF(DAY, 1, CURRENT_TIMESTAMP)) AND (dbo.invoices.invoiceDatePaid < DATEDIFF(DAY, 0,
CURRENT_TIMESTAMP)) AND (dbo.companies.companyPaymentType = 3)
ORDER BY dbo.invoices.invoiceId DESC
In the Payment_Type column i want to add the SUM of the Value column to the word 'Bacs' so it reads 'Bacs £sum' to 2 decimal places. Could you help please, regards and thanks for all the help and suggestions already provided
I'm not very much clear to what exactly you need. You need complete sum of entire column to be displayed or in a group manner, but here is what you can try..Add the sum(Value) after converting it to varchar,which is necessary as two data types has to be varchar to concenate and group by all the remaining columns..something like this
....
,'Bacs'+cast(sum(dbo.invoices.invoiceTotal)
as varchar) AS Payment_type
...
group by all remaining columns
...
order by clause
I don't know whether it even close to what you need but it's just a try to help :-)