I'm using the below code to get the count of every case statements which has sum inside the case statements but I'm getting the error message.
SELECT
count(case when SUM(Orders.Sales)>10000 then 1 end) as High,
count(case when SUM(Orders.Sales)>5000 and SUM(Orders.Sales)<9999 then
SUM(Orders.Sales) end) as Medium,
count(case when SUM(Orders.Sales)<5000 then SUM(Orders.Sales) end) as Low
FROM Orders
INNER JOIN Returns ON Orders.[Order ID] = Returns.[Order ID]
OUTPUT
This is the required output which I'm supposed to be expected.
I feel that you should be doing the outer count rollups over a subquery which aggregates by order:
SELECT
COUNT(CASE WHEN sales < 5000 THEN 1 END) AS Low,
COUNT(CASE WHEN sales < 9999 THEN 1 END) AS Medium,
COUNT(CASE WHEN sales >= 9999 THEN 1 END) AS High
FROM
(
SELECT o.[Order ID], SUM(o.Sales) AS sales
FROM Orders o
INNER JOIN Returns r ON o.[Order ID] = r.[Order ID]
GROUP BY o.[Order ID]
) t;
That being said, I don't actually know what the purpose of joining Orders to the Returns table is. If you intend to only find sales amounts from orders which have been returned, then maybe this makes sense. Otherwise, maybe it doesn't make sense.
I have list of line items from invoices with a field that indicates if a line was delivered or picked up. I need to find a percentage of delivered items from the total number of lines.
SALES_NBR | Total | Deliveryrate
1 = Delivered 0 = picked up from FULFILLMENT.
SELECT SALES_NBR,
COUNT (ITEMS) as Total,
SUM (case when FULFILLMENT = '1' then 1 else 0 end) as delivered,
(SELECT delivered/total) as Deliveryrate
FROM Invoice_table
WHERE STORE IN '0123'
And SALE_DATE >='2020-02-01'
And SALE_DATE <='2020-02-07'
Group By SALES_NBR, Deliveryrate;
My query executes but never finishes for some reason. Is there any easier way to do this? Fulfillment field does not contain any NULL values.
Any help would be appreciated.
I need to find a percentage of delivered items from the total number of lines.
The simplest method is to use avg():
select SALES_NBR,
avg(fulfillment) as delivered_ratio
from Invoice_table
where STORE = '0123' and
SALE_DATE >='2020-02-01' and
SALE_DATE <='2020-02-07'
group by SALES_NBR;
I'm not sure if the group by sales_nbr is needed.
If you want to get a "nice" query, you can use subqueries like this:
select
qry.*,
qry.delivered/qry.total as Deliveryrate
from (
select
SALES_NBR,
count(ITEMS) as Total,
sum(case when FULFILLMENT = '1' then 1 else 0 end) as delivered
from Invoice_table
where STORE IN '0123'
and SALE_DATE >='2020-02-01'
and SALE_DATE <='2020-02-07'
group by SALES_NBR
) qry;
But I think this one, even being ugglier, could perform faster:
select
SALES_NBR,
count(ITEMS) as Total,
sum(case when FULFILLMENT = '1' then 1 else 0 end) as delivered,
sum(case when FULFILLMENT = '1' then 1 else 0 end)/count(ITEMS) as Deliveryrate
from Invoice_table
where STORE IN '0123'
and SALE_DATE >='2020-02-01'
and SALE_DATE <='2020-02-07'
group by SALES_NBR
I am querying two tables from an oracle database. POS.SNAPSHOT_SUMMARY_LOG contains daily snapshots of all reserved orders from today into the future. POS.SALES_SUMMARY_LOG contains final sales history until yesterday. I am trying to create a denormalized table that has a column with sales figures at different points in time (i.e. WINDOWS). The query below works well and is fast. I get a column for each sum for each window. See results for 2/26/18-3/26/18 windows_query. (The PREVIOUS_YEAR__DATE column is the most similar weekday from the previous year and not the same calendar date of the previous year)
However, I can't figure out how to group by the dimensions of PRODUCT_CATEGORY, CUSTOMER_CATEGORY, SALES_CHANNEL to the results so that the query runs quickly.
WITH SNAP AS( SELECT
TRUNC(SYSDATE,'DDD')-SNAPSHOT_DATE AS WINDOW, CURRENT_YEAR_DATE, PREVIOUS_YEAR__DATE, PRODUCT_CATEGORY, CUSTOMER_CATEGORY, SALES_CHANNEL, QUANTITY, REVENUE
FROM POS.SNAPSHOT_SUMMARY_LOG
WHERE (SNAPSHOT_DATE IN (TRUNC(SYSDATE,'DDD'), TRUNC(SYSDATE,'DDD')-7, TRUNC(SYSDATE,'DDD')-365,TRUNC(SYSDATE,'DDD')-372))),
HIST AS (SELECT CURRENT_YEAR_DATE, PREVIOUS_YEAR__DATE, PRODUCT_CATEGORY, CUSTOMER_CATEGORY, SALES_CHANNEL, QUANTITY, REVENUE
FROM POS.SALES_SUMMARY_LOG)
SELECT DISTINCT SNAP.CURRENT_YEAR_DATE, SNAP.PREVIOUS_YEAR__DATE,
CONCAT(SNAP0.REVENUE,HIST0.REVENUE)+0 AS REVENUE0,
CONCAT(SNAP7.REVENUE,HIST7.REVENUE)+0 AS REVENUE7,
CONCAT(SNAP365.REVENUE,HIST365.REVENUE)+0 AS REVENUE365,
CONCAT(SNAP372.REVENUE,HIST372.REVENUE)+0 AS REVENUE372,
CONCAT(SNAP0.QUANTITY,HIST0.QUANTITY)+0 AS QUANTITY0,
CONCAT(SNAP7.QUANTITY,HIST7.QUANTITY)+0 AS QUANTITY7,
CONCAT(SNAP365.QUANTITY,HIST365.QUANTITY)+0 AS QUANTITY365,
CONCAT(SNAP372.QUANTITY,HIST372.QUANTITY)+0 AS QUANTITY372
FROM SNAP
LEFT OUTER JOIN (SELECT CURRENT_YEAR_DATE, sum(REVENUE) AS REVENUE, sum(QUANTITY) AS QUANTITY FROM SNAP WHERE WINDOW=0 GROUP BY CURRENT_YEAR_DATE) SNAP0 ON SNAP.CURRENT_YEAR_DATE=SNAP0.CURRENT_YEAR_DATE
LEFT OUTER JOIN (SELECT CURRENT_YEAR_DATE, sum(REVENUE) AS REVENUE, sum(QUANTITY) AS QUANTITY FROM SNAP WHERE WINDOW=7 GROUP BY CURRENT_YEAR_DATE) SNAP7 ON SNAP.CURRENT_YEAR_DATE=SNAP7.CURRENT_YEAR_DATE
LEFT OUTER JOIN (SELECT CURRENT_YEAR_DATE, sum(REVENUE) AS REVENUE, sum(QUANTITY) AS QUANTITY FROM SNAP WHERE WINDOW=365 GROUP BY CURRENT_YEAR_DATE ) SNAP365 ON SNAP.PREVIOUS_YEAR_DATE=SNAP365.CURRENT_YEAR_DATE
LEFT OUTER JOIN (SELECT CURRENT_YEAR_DATE, sum(REVENUE) AS REVENUE, sum(QUANTITY) AS QUANTITY FROM SNAP WHERE WINDOW=372 GROUP BY CURRENT_YEAR_DATE) SNAP372 ON SNAP.PREVIOUS_YEAR_DATE=SNAP372.CURRENT_YEAR_DATE
LEFT OUTER JOIN (SELECT CURRENT_YEAR_DATE, sum(REVENUE) AS REVENUE, sum(QUANTITY) AS QUANTITY FROM HIST WHERE CURRENT_YEAR_DATE<TRUNC(SYSDATE,'DDD')-0 GROUP BY CURRENT_YEAR_DATE) HIST0 ON SNAP.CURRENT_YEAR_DATE=HIST0.CURRENT_YEAR_DATE
LEFT OUTER JOIN (SELECT CURRENT_YEAR_DATE, sum(REVENUE) AS REVENUE, sum(QUANTITY) AS QUANTITY FROM HIST WHERE CURRENT_YEAR_DATE<TRUNC(SYSDATE,'DDD')-7 GROUP BY CURRENT_YEAR_DATE) HIST7 ON SNAP.CURRENT_YEAR_DATE=HIST7.CURRENT_YEAR_DATE
LEFT OUTER JOIN (SELECT CURRENT_YEAR_DATE, sum(REVENUE) AS REVENUE, sum(QUANTITY) AS QUANTITY FROM HIST WHERE CURRENT_YEAR_DATE<TRUNC(SYSDATE,'DDD')-365 GROUP BY CURRENT_YEAR_DATE) HIST365 ON SNAP.PREVIOUS_YEAR_DATE=HIST365.CURRENT_YEAR_DATE
LEFT OUTER JOIN (SELECT CURRENT_YEAR_DATE, sum(REVENUE) AS REVENUE, sum(QUANTITY) AS QUANTITY FROM HIST WHERE CURRENT_YEAR_DATE<TRUNC(SYSDATE,'DDD')-372 GROUP BY CURRENT_YEAR_DATE) HIST372 ON SNAP.PREVIOUS_YEAR_DATE=HIST372.CURRENT_YEAR_DATE
WHERE SNAP.CURRENT_YEAR_DATE BETWEEN TRUNC(SysDate,'YEAR') AND ADD_MONTHS(TRUNC(TRUNC(SysDate,'YEAR'),'Y'),15)
I think you can rewrite your query using conditional aggregation, which ought to be a lot more performant than your current query.
E.g. I think you could rewrite it to be something like:
SELECT current_year_date,
previous_year__date,
SUM(CASE WHEN trunc(sysdate) - snapshot_date = 0 THEN revenue END) snap_revenue0,
SUM(CASE WHEN trunc(sysdate) - snapshot_date = 7 THEN revenue END) snap_revenue7,
SUM(CASE WHEN trunc(sysdate) - snapshot_date = 365 THEN revenue END) snap_revenue365,
SUM(CASE WHEN trunc(sysdate) - snapshot_date = 372 THEN revenue END) snap_revenue372,
SUM(CASE WHEN CURRENT_YEAR_DATE < (trunc(sysdate) - 0 THEN revenue END) hist_revenue0,
SUM(CASE WHEN CURRENT_YEAR_DATE < (trunc(sysdate) - 7 THEN revenue END) hist_revenue7,
SUM(CASE WHEN CURRENT_YEAR_DATE < (trunc(sysdate) - 365 THEN revenue END) hist_revenue365,
SUM(CASE WHEN CURRENT_YEAR_DATE < (trunc(sysdate) - 372 THEN revenue END) hist_revenue372,
SUM(CASE WHEN trunc(sysdate) - snapshot_date = 0 THEN quantity END) snap_quantity0,
SUM(CASE WHEN trunc(sysdate) - snapshot_date = 7 THEN quantity END) snap_quantity7,
SUM(CASE WHEN trunc(sysdate) - snapshot_date = 365 THEN quantity END) snap_quantity365,
SUM(CASE WHEN trunc(sysdate) - snapshot_date = 372 THEN quantity END) snap_quantity372,
SUM(CASE WHEN CURRENT_YEAR_DATE < (trunc(sysdate) - 0 THEN quantity END) hist_quantity0,
SUM(CASE WHEN CURRENT_YEAR_DATE < (trunc(sysdate) - 7 THEN quantity END) hist_quantity7,
SUM(CASE WHEN CURRENT_YEAR_DATE < (trunc(sysdate) - 365 THEN quantity END) hist_quantity365,
SUM(CASE WHEN CURRENT_YEAR_DATE < (trunc(sysdate) - 372 THEN quantity END) hist_quantity372
FROM pos.snapshot_summary_log
GROUP BY current_year_date,
previous_year__date;
I don't quite understand what you mean by "add the dimensions of PRODUCT_CATEGORY, CUSTOMER_CATEGORY, SALES_CHANNEL"; if you mean you want the results grouped with those additional columns, then it's simply a matter of adding them into the above select column and group by lists, e.g.:
SELECT current_year_date,
previous_year__date,
product_category,
customer_category,
sales_channel,
<SUM columns>
FROM pos.snapshot_summary_log
GROUP BY current_year_date,
previous_year__date,
product_category,
customer_category,
sales_channel;
I've not done anything with the columns; you may want to throw an outer query around this that adds the snap and hist columns together, or maybe COALESCEs them, but I'll leave that up to you to decide.
How to reduce the number of SUM functions in my query?
SELECT P_NAME "Product name", (SUM(case when PR = 1 then QUANTITY end) -
SUM(case when PR = 2 then QUANTITY end)) "End balance",
CAST((SUM(case when PR = 1 then QUANTITY*PRICE end) - SUM(case when PR = 2 then
QUANTITY*PRICE end)) as decimal(13,2)) "End balance" FROM RPOD, DMS, DMZ
WHERE RPOD.KTOV=DMS.KTOV AND DMZ.NDM=DMS.DMZ_FK
GROUP BY P_NAME
ORDER BY P_NAME;
You can combine them:
SELECT P_NAME as "Product name",
SUM(case when PR = 1 then QUANTITY
when PR = 2 then - QUANTITY
end) as "End balance",
SUM(case when PR = 1 then QUANTITY * PRICE
when PR = 2 then - QUANTITY * PRICE
end) as "End balance/price",
FROM RPOD JOIN
DMS
ON RPOD.KTOV = DMS.KTOV JOIN
DMZ
ON DMZ.NDM = DMS.DMZ_FK
GROUP BY P_NAME
ORDER BY P_NAME;
Much more important aesthetics about SUM()s is learning to use proper, explicit JOIN syntax. Never use commas in the JOIN clause. Also, you should not give two columns in the result set the same name.
I've got to design a query in visual studio where I have 2 data sets.
basically it goes like this.
I want to compare this weeks call total to last week per country calling.
the only thing is last weeks calls may have come from 20 diff countries while this weeks might only have come from 15.
How can I make the query such that the 20 countries will show up for both while having "0" value in for countries that do not appear this week.
below is my query:
Select country,
Sum(Case When actstatus in (5,105) Then 1 Else 0 End) As TotalCalls,
Sum(Case When actstatus = 105 Then 1 Else 0 End) As FailedCalls
From termactivity(nolock)
INNER JOIN termconfig(NOLOCK) ON cfgterminalID = actterminalID
INNER JOIN Country (nolock) on country = cycode
Where actstatus in (5,105)
and (actTerminalDateTime BETWEEN #StartDate-7 AND #EndDate-7)
Group By country
order By country asc
When Act status = 105 it means the call was not completed and when it = 5 it means the call was successful. I am doing this to get a successful call % rate per week.
Thanks in Advance!
Apply the same logic as you did to total calls and failed calls as you did to the this week and last week.
SELECT country,
COUNT(CASE WHEN actTerminalDateTime < #StartDate THEN 1 END) [LastWeekTotalCalls],
COUNT(CASE WHEN ActStatus = 105 AND actTerminalDateTime < #StartDate THEN 1 END) [LastWeekFailedCalls],
COUNT(CASE WHEN actTerminalDateTime >= #StartDate THEN 1 END) [ThisWeekTotalCalls],
COUNT(CASE WHEN ActStatus = 105 AND actTerminalDateTime >= #StartDate THEN 1 END) [ThisWeekFailedCalls]
FROM termactivity (NOLOCK)
INNER JOIN termconfig (NOLOCK)
ON cfgterminalID = actterminalID
INNER JOIN Country (NOLOCK)
ON country = cycode
WHERE actstatus in (5,105)
AND actTerminalDateTime BETWEEN DATEADD(DAY, -7, #StartDate) AND #EndDate
GROUP BY country
ORDER BY country ASC
I've also tidied up your query slightly, for example there is no point in specifying
WHEN ActStatus IN (5, 105) ...
When your WHERE clause already limits all results to 5, 105, therefore this is a redundant predicate in your case expression
From what I understand, you want to perform separate queries for two weeks, and you want both queries to produce rows for all countries, regardless of whether all countries had any calls. To achieve this, you need to use LEFT OUTER JOINS. The below code should guarantee that every country found in the Country table has a row, even if both sums are 0.
SELECT country,
SUM(CASE WHEN actstatus IN (5,105) THEN 1 ELSE 0 END) AS TotalCalls,
SUM(CASE WHEN actstatus = 105 THEN 1 ELSE 0 END) AS FailedCalls
FROM Country (NOLOCK)
LEFT OUTER JOIN termconfig (NOLOCK) ON country = cycode
LEFT OUTER JOIN termactivity (NOLOCK) ON cfgterminalID = actterminalID
WHERE (actTerminalDateTime BETWEEN #StartDate-7 AND #EndDate-7)
GROUP BY country
ORDER BY country ASC
If this was not what you wanted, perhaps you need to clarify your question. Many others have assumed that you want to combine the results into a single query.