Using DB2 column alias within same select - sql

I have a working query but I'm trying to use the column aliases in order to create more calculations in my select and it says the column can't be found (i.e. it can't use the alias).
For instance, the working query:
select employee,
sum(case when date_field between '2018-01-01' and '2018-01-31' and category = 'CategoryOne' then salesprice else 0 end) as priorDate,
sum(case when date_field between '2018-01-01' and '2018-01-31' then salesprice else 0 end) as priorTotal,
cast(Round((DEC(sum(case when date_field between '2018-01-01' and '2018-01-31' and category = 'CategoryOne' then salesprice else 0 end),12,2)/sum(case when date_field between '2018-01-01' and '2018-01-31' then salesprice else 0 end)) * 100,2) as decimal(12,2)) as priorPercent,
sum(case when date_field between '2019-01-01' and '2019-01-31' and category = 'CategoryOne' then salesprice else 0 end) as currentDate,
sum(case when date_field between '2019-01-01' and '2019-01-31' then salesprice else 0 end) as currentSales,
cast(Round((DEC(sum(case when date_field between '2019-01-01' and '2019-01-31' and category = 'CategoryOne' then salesprice else 0 end),12,2)/sum(case when date_field between '2019-01-01' and '2019-01-31' then salesprice else 0 end)) * 100,2) as decimal(12,2)) as currentPercent
from table
group by employee;
But for my two percentages (the two rows that start with cast) I've tried using just priorDate / priorTotal but it won't work and so I have to repeat the 2 whole calculations as a percentage.
I want to also obtain a difference in percentages which would be much easier to declare by using the aliases, and maybe more performant?

You can write this using a CTE/subquery:
with t as (
select employee,
sum(case when date_field between '2018-01-01' and '2018-01-31' and category = 'CategoryOne' then salesprice else 0 end) as priorDate,
sum(case when date_field between '2018-01-01' and '2018-01-31' then salesprice else 0 end) as priorTotal,
sum(case when date_field between '2019-01-01' and '2019-01-31' and category = 'CategoryOne' then salesprice else 0 end) as currentDate,
sum(case when date_field between '2019-01-01' and '2019-01-31' then salesprice else 0 end) as currentSales,
from table
group by employee
)
select t.*,
round(t.priorDate * 100.0 / nullif(t.priorTotal, 0), 2) as priorPercent,
round(t.priorTotal * 100.0 / nullif(t.currentTotal, 0), 2) as currentPercent
from t;

Related

Subquery In Postgresql not matching data expected

When the query below is used I get 7 records from the database.
SELECT pickup_date::date,
SUM(CASE WHEN paid ='Yes' THEN price ELSE 0 END) AS TotalMoMoPaid
from requests
where order_status = 'Done'
and payment_mode = 'MoMo'
and pickup_date::date >= current_timestamp::date - INTERVAL '7 days'
GROUP BY pickup_date::date,paid,order_status,price
When the same query is used as a sub query, I get 2 records which is not what I expect,
SELECT pickup_date::date,
sub.TotalMoMoPaid,
SUM(CASE WHEN order_status ='Done' THEN price ELSE 0 END) AS "TotalCashSales"
from (
SELECT paid as subPaid,
order_status as subStatus,
price as subPrice,
SUM(CASE WHEN paid ='Yes' THEN price ELSE 0 END) AS TotalMoMoPaid
from requests
where order_status = 'Done'
and payment_mode = 'MoMo'
and pickup_date::date >= current_timestamp::date - INTERVAL '7 days'
GROUP BY pickup_date::date,subPaid,subStatus,subPrice
) AS sub, requests
where order_status ='Done'
and payment_mode = 'Cash'
and pickup_date::date >= current_timestamp::date - INTERVAL '7 days'
GROUP BY sub.TotalMoMoPaid,subPaid,pickup_date::date
ORDER BY sub.TotalMoMoPaid,pickup_date::date
This query should work instead of using subqueries;
SELECT pickup_date::date,
SUM(CASE WHEN payment_mode = 'MoMo' and paid = 'Yes' THEN price ELSE 0 END) AS TotalMoMoPaid,
SUM(CASE WHEN payment_mode = 'Cash' and paid = 'Yes' THEN price ELSE 0 END) AS TotalCashSales
FROM requests
WHERE order_status = 'Done'
and pickup_date::date >= current_timestamp::date - INTERVAL '7 days'
GROUP BY pickup_date::date,paid,order_status,price

Speed up Query Run Time with multiple Case When Expressions

I have the following code below. It is a simple Sum with specific conditions and divided by count distinct function with specific conditions. The problem it is taking too long to run. Right now it is 2 Days and it has not finished running. How can I make this faster? This is part of the code the Case whens are repeated over 100 times as I am tracking over every month.
Select
(sum (case when INSTALLATION_TYPE like'%R' and RATE_FAKT = 'VI' and INvoice_Date between '2018-01-01' and '2018-12-31' then QUANT end)/1000)/
Count (Distinct (case when INSTALLATION_TYPE like'%R' and RATE_FAKT = 'VI' and INvoice_Date between '2018-01-01' and '2018-12-31' then MIRN end) )CY18_GJPERMIRN_VI,
(sum (case when RATE_FAKT = 'VB' and INvoice_Date between '2018-01-01' and '2018-12-31' then QUANT end)/1000)/
Count (Distinct (case when INSTALLATION_TYPE like'%R' and RATE_FAKT = 'VB' and INvoice_Date between '2018-01-01' and '2018-12-31' then MIRN end) )CY18_GJPERMIRN_VB,
(sum (case when INSTALLATION_TYPE like'%B' and RATE_FAKT = 'VI' and INvoice_Date between '2018-01-01' and '2018-12-31' then QUANT end)/1000)/
Count (Distinct (case when INSTALLATION_TYPE like'%B' and RATE_FAKT = 'VI' and INvoice_Date between '2018-01-01' and '2019-12-31' then MIRN end) )CY18_GJPERMIRN_VI_Commercial,
(sum (case when INSTALLATION_TYPE like'%R' and RATE_FAKT = 'VI' and INvoice_Date between '2019-01-01' and '2019-08-31' then QUANT end)/1000)/
Count (Distinct (case when INSTALLATION_TYPE like'%R' and RATE_FAKT = 'VI' and INvoice_Date between '2019-01-01' and '2019-08-31' then MIRN end) )CY19_AUG_GJPERMIRN_VI,
(sum (case when RATE_FAKT = 'VB' and INvoice_Date between '2019-01-01' and '2019-08-31' then QUANT end)/1000)/
Count (Distinct (case when INSTALLATION_TYPE like'%R' and RATE_FAKT = 'VB' and INvoice_Date between '2019-01-01' and '2019-08-31' then MIRN end) )CY19_AUG_GJPERMIRN_VB,
(sum (case when INSTALLATION_TYPE like'%B' and RATE_FAKT = 'VI' and INvoice_Date between '2019-01-01' and '2019-08-31' then QUANT end)/1000)/
Count (Distinct (case when INSTALLATION_TYPE like'%B' and RATE_FAKT = 'VI' and INvoice_Date between '2019-01-01' and '2019-08-31' then MIRN end) )CY19_AUG_GJPERMIRN_VI_Commercial
FROM [Analytics_JGN].[dbo].[VW_BILLINGS]
Where MIRN like '524%';
You need to use dynamic PIVOT query to generate columns dynamically. This link will help you in it.
Because I checked that there are 3 columns (GJPERMIRN_VI, GJPERMIRN_VB, GJPERMIRN_VI_Commercial) are repeating year wise and prefix is CY(Last 2 character of year from Invoice date column)_.
I have changed your query from CASE statement to UNION ALL with CTE. This will little bit faster. Please check below query for your answer.
;WITH CTE_GJPERMIRN
AS
(
SELECT
(SUM(ISNULL(QUANT,0)) / 1000) / ISNULL(COUNT(DISTINCT MIRN),1) AS CY18_GJPERMIRN_VI,
0 AS CY18_GJPERMIRN_VB,
0 AS CY18_GJPERMIRN_VI_Commercial,
0 AS CY19_AUG_GJPERMIRN_VI,
0 AS CY19_AUG_GJPERMIRN_VB,
0 AS CY19_AUG_GJPERMIRN_VI_Commercial
FROM [Analytics_JGN].[dbo].[VW_BILLINGS]
Where MIRN LIKE '524%'
AND INSTALLATION_TYPE LIKE '%R'
AND RATE_FAKT = 'VI'
AND INvoice_Date BETWEEN '2018-01-01' AND '2018-12-31'
UNION ALL
SELECT
0 AS CY18_GJPERMIRN_VI,
(SUM(ISNULL(QUANT,0)) / 1000) / ISNULL(COUNT(DISTINCT MIRN),1) AS CY18_GJPERMIRN_VB,
0 AS CY18_GJPERMIRN_VI_Commercial,
0 AS CY19_AUG_GJPERMIRN_VI,
0 AS CY19_AUG_GJPERMIRN_VB,
0 AS CY19_AUG_GJPERMIRN_VI_Commercial
FROM [Analytics_JGN].[dbo].[VW_BILLINGS]
Where MIRN LIKE '524%'
AND INSTALLATION_TYPE LIKE '%R'
AND RATE_FAKT = 'VB'
AND INvoice_Date BETWEEN '2018-01-01' AND '2018-12-31'
UNION ALL
SELECT
0 AS CY18_GJPERMIRN_VI,
0 AS CY18_GJPERMIRN_VB,
(SUM(ISNULL(QUANT,0)) / 1000) / ISNULL(COUNT(DISTINCT MIRN),1) AS CY18_GJPERMIRN_VI_Commercial,
0 AS CY19_AUG_GJPERMIRN_VI,
0 AS CY19_AUG_GJPERMIRN_VB,
0 AS CY19_AUG_GJPERMIRN_VI_Commercial
FROM [Analytics_JGN].[dbo].[VW_BILLINGS]
Where MIRN LIKE '524%'
AND INSTALLATION_TYPE LIKE '%B'
AND RATE_FAKT = 'VI'
AND INvoice_Date BETWEEN '2018-01-01' AND '2018-12-31' --Consider 2018 year in End Date instead of 2019 in count distinct case statement
UNION ALL
SELECT
0 AS CY18_GJPERMIRN_VI,
0 AS CY18_GJPERMIRN_VB,
0 AS CY18_GJPERMIRN_VI_Commercial,
(SUM(ISNULL(QUANT,0)) / 1000) / ISNULL(COUNT(DISTINCT MIRN),1) AS CY19_AUG_GJPERMIRN_VI,
0 AS CY19_AUG_GJPERMIRN_VB,
0 AS CY19_AUG_GJPERMIRN_VI_Commercial
FROM [Analytics_JGN].[dbo].[VW_BILLINGS]
Where MIRN LIKE '524%'
AND INSTALLATION_TYPE LIKE'%R'
AND RATE_FAKT = 'VI'
AND INvoice_Date BETWEEN '2019-01-01' AND '2019-08-31'
UNION ALL
SELECT
0 AS CY18_GJPERMIRN_VI,
0 AS CY18_GJPERMIRN_VB,
0 AS CY18_GJPERMIRN_VI_Commercial,
0 AS CY19_AUG_GJPERMIRN_VI,
(SUM(ISNULL(QUANT,0)) / 1000) / ISNULL(COUNT(DISTINCT MIRN),1) AS CY19_AUG_GJPERMIRN_VB,
0 AS CY19_AUG_GJPERMIRN_VI_Commercial
FROM [Analytics_JGN].[dbo].[VW_BILLINGS]
Where MIRN LIKE '524%'
AND INSTALLATION_TYPE LIKE '%R'
AND RATE_FAKT = 'VB'
AND INvoice_Date BETWEEN '2019-01-01' AND '2019-08-31'
UNION ALL
SELECT
0 AS CY18_GJPERMIRN_VI,
0 AS CY18_GJPERMIRN_VB,
0 AS CY18_GJPERMIRN_VI_Commercial,
0 AS CY19_AUG_GJPERMIRN_VI,
0 AS CY19_AUG_GJPERMIRN_VB,
(SUM(ISNULL(QUANT,0)) / 1000) / ISNULL(COUNT(DISTINCT MIRN),1) AS CY19_AUG_GJPERMIRN_VI_Commercial
FROM [Analytics_JGN].[dbo].[VW_BILLINGS]
Where MIRN LIKE '524%'
AND INSTALLATION_TYPE LIKE '%B'
AND RATE_FAKT = 'VI'
AND INvoice_Date BETWEEN '2019-01-01' AND '2019-08-31'
)
SELECT
SUM(CG.CY18_GJPERMIRN_VI) AS CY18_GJPERMIRN_VI,
SUM(CG.CY18_GJPERMIRN_VB) AS CY18_GJPERMIRN_VB,
SUM(CG.CY18_GJPERMIRN_VI_Commercial) AS CY18_GJPERMIRN_VI_Commercial,
SUM(CG.CY19_AUG_GJPERMIRN_VI) AS CY19_AUG_GJPERMIRN_VI,
SUM(CG.CY19_AUG_GJPERMIRN_VB) AS CY19_AUG_GJPERMIRN_VB,
SUM(CG.CY19_AUG_GJPERMIRN_VI_Commercial) AS CY19_AUG_GJPERMIRN_VI_Commercial
FROM CTE_GJPERMIRN CG
Note: CY18_GJPERMIRN_VI_Commercial - You may put wrong end date in COUNT(DISTINCT) Invoice date case statement, which I have corrected.
For performance troubleshooting you can try using many separate select statements instead of many case statements in 1 select statement. Something like: (untested)
select *
from (
Select sum(isnull(QUANT,0)/1000/Count(Distinct MIRN) CY18_GJPERMIRN_VI
FROM [Analytics_JGN].[dbo].[VW_BILLINGS]
Where MIRN like '524%'
and INSTALLATION_TYPE like'%R'
and RATE_FAKT = 'VI'
and INvoice_Date between '2018-01-01' and '2018-12-31'
) a
full outer join
(
select sum(isnull(QUANT,0)/1000/Count(Distinct(MIRN) CY18_GJPERMIRN_VB
FROM [Analytics_JGN].[dbo].[VW_BILLINGS]
Where MIRN like '524%'
and RATE_FAKT = 'VB'
and INvoice_Date between '2018-01-01' and '2018-12-31'
) b on 1=1
Or another approach is to use group by instead of case statements -- presuming it is reasonable. The date ranges would still need to be case statements, but RATE_FAKT and INSTALLATION_TYPE could most likely be moved to GROUP BY.
Your query can be optimized in 2-4 steps because of communication problem.1. First you load the require data in Temp table.2. Since you are saying that this is only part of code so consider my script to incomplete as well.
CREATE TABLE #temp
(
INSTALLATION_TYPE VARCHAR(1),
RATE_FAKT VARCHAR(2) ,
INvoice_Date DATETIME,
QUANT INT,
MIRN INT
)
INSERT INTO #temp
(
INSTALLATION_TYPE,
RATE_FAKT,
INvoice_Date,
QUANT,
MIRN
)
SELECT
RIGHT(INSTALLATION_TYPE,1),
RATE_FAKT,
INvoice_Date,
QUANT,
MIRN
FROM [Analytics_JGN].[dbo].[VW_BILLINGS]
WHERE INvoice_Date >= '2018-01-01'
AND INvoice_Date <= '2019-12-31'
SELECT * FROM #temp
DROP TABLE #temp;

Removing Null results from AVG

I've been doing some work regarding AVG. My previous solution didn't work. However, after some revision and help it's now returning the correct results. The results do however, keep returning NULL Values for agents as they don't have results in the CASE WHEN date range.
I've tried adding IS NOT NULL into CASE WHEN argument but it tells me the expression does not exist.
SELECT Employee,
AVG(CASE WHEN SaleDate >= '2019-01-01' AND SaleDate < '2019-04-01' THEN NewScheme END),
AVG(CASE WHEN SaleDate >= '2019-01-04' AND SaleDate < '2019-04-07' THEN NewScheme END),
FROM Salereport
WHERE Business Area = 'Sales'
GROUP BY Employee;
When adding is not null i'm told the expression doesn't exist.
You can simply add a WHERE clause to remove employees that do not have sales in either range. It could still show NULL in one of the average columns though:
SELECT Employee,
AVG(CASE WHEN SaleDate >= '2019-01-01' AND SaleDate < '2019-04-01' THEN NewScheme END),
AVG(CASE WHEN SaleDate >= '2019-01-04' AND SaleDate < '2019-04-07' THEN NewScheme END)
FROM Salereport
WHERE Business Area = 'Sales'
AND SaleDate >= '2019-01-01' AND SaleDate < '2019-04-07'
-- if the ranges do not overlap then list them separately and combine with "OR"
GROUP BY Employee;
Build your query like this. Put ELSE 0 End and ISNULL() to avoid nulls your your AVG
SELECT Employee,
AVG(ISNULL(CASE WHEN SaleDate >= '2019-01-01' AND SaleDate < '2019-04-01'
THEN NewScheme ELSE 0 End, 0)
END),
AVG(ISNULL((CASE WHEN SaleDate >= '2019-01-04' AND SaleDate < '2019-04-07'
THEN NewScheme ELSE 0 End, 0)
END),
FROM Salereport
WHERE Business Area = 'Sales'
GROUP BY Employee;
OR
SELECT Employee,
AVG(CASE WHEN SaleDate >= '2019-01-01' AND SaleDate < '2019-04-01'
THEN ISNULL(NewScheme, 0) ELSE 0 End
END),
AVG((CASE WHEN SaleDate >= '2019-01-04' AND SaleDate < '2019-04-07'
THEN ISNULL(NewScheme, 0) ELSE 0 End
END),
FROM Salereport
WHERE Business Area = 'Sales'
GROUP BY Employee;

SSRS: how to get top 3 in order Z to A

I try to get in my diagram the top 3 of the worst value in SSRS:
my Code:
SELECT *
FROM (
Select top 3
intervaldate as Datum
,Name
,teamname as Team
,SUM(case when CounterName = 'Blown away' then calculationUnits else 0 end) as Blown
,Sum(case when CounterName = 'Thrown away' then calculationUnits else 0 end) as Thrown
,Sum(case when CounterName = 'total' then calculationUnits else 0 end) as Total
from Counting
where IntervalDate >= dateadd(day,datediff(day,1,GETDATE()),0)
AND IntervalDate < dateadd(day,datediff(day,0,GETDATE()),0)
and Name in (Select SystemID from tSystemView where SystemViewID = 2)
group by intervaldate, teamName, Name
) c
Expression of the diagram:
=Sum(Fields!Blown.Value + Fields!Thrown.Value) / Sum(Fields!Total.Value) * 100
And I sorted it from highest to lowest
But it does not show me the right order.
If I choose every "Name" then it shows me other value then the top 3:
all Names with value:
top 3:
It's because your top 3 statement is in the SQL while your sort is in the report. Without an order by SQL picks the top 3 random records. Also, unless there is more SQL you are not showing, the outer select is unnecessary. Add an order by <column> desc below your group by.
with Calcs as
(
select intervaldate as Datum,
Name,
TeamName,
SUM(case when CounterName = 'Blown away' then calculationUnits else 0 end) as Blown,
Sum(case when CounterName = 'Thrown away' then calculationUnits else 0 end) as Thrown,
Sum(case when CounterName = 'total' then calculationUnits else 0 end) as Total
from Counting
where IntervalDate >= dateadd(day,datediff(day,1,GETDATE()),0)
AND IntervalDate < dateadd(day,datediff(day,0,GETDATE()),0)
and Name in (Select SystemID from tSystemView where SystemViewID = 2)
group by intervaldate, teamName, Name
)
select b.*
from
(
select a.*, row_number() over (order by (Blown + Thrown)/Total desc) as R_Ord -- Change between ASC/DESC depending on needs
from Calcs a
) b
where R_Ord <=3

Revenue for two months date wise

I am trying to get data for last 2 month ...but the query does not give perfect result....
SELECT DAY(table_A.PaymentDate) as date1 ,
(case when MONTH(table_A.PaymentDate) = MONTH(CURRENT_TIMESTAMP) - 1
then CAST(SUM(table_A.Total_Amount) AS INT)
else 0
end) AS last_month_CNT,
(case when MONTH(table_A.PaymentDate) = MONTH(CURRENT_TIMESTAMP)
then CAST(SUM(table_A.Total_Amount) As INT)
else 0
end) as This_month_CNT
FROM Tbl_Pan_Paymentdetails table_A
FULL OUTER JOIN Tbl_Pan_Paymentdetails table_B
ON table_A.PaymentDate=table_B.PaymentDate
WHERE YEAR(table_A.PaymentDate) = YEAR(CURRENT_TIMESTAMP)
AND
table_A.PaymentDate >= DATEADD(MONTH, -1, GETDATE())
GROUP BY
DAY(table_A.PaymentDate) ,MONTH(table_A.PaymentDate)
order by
DAY(table_A.PaymentDate);
Move the entire case expression inside the sum function and don't include the month in the group by. Also, the full outer join seems unnecessary so I removed it.
This should be what you are looking for:
SELECT
DAY(PaymentDate) as date1 ,
SUM(CASE WHEN MONTH(PaymentDate) = MONTH(CURRENT_TIMESTAMP)-1 THEN CAST(Total_Amount AS INT) ELSE 0 END) AS last_month_CNT,
SUM(CASE WHEN MONTH(PaymentDate) = MONTH(CURRENT_TIMESTAMP) THEN CAST(Total_Amount AS INT) ELSE 0 END) AS This_month_CNT
FROM Tbl_Pan_Paymentdetails
WHERE YEAR(PaymentDate) = YEAR(CURRENT_TIMESTAMP)
AND PaymentDate >= DATEADD(MONTH, -1, GETDATE())
GROUP BY DAY(PaymentDate)
ORDER BY DAY(PaymentDate);