Speed up Query Run Time with multiple Case When Expressions - sql

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;

Related

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;

I need to select clients who have multiple records in one column

I'm tasked with selecting all clients who have traveled in 2017 and 2018, but not 2019.
I've tried something like the below but it doesn't work. I'm pretty much a novice at SQL, VBA is more my thing.
I could say where tour date is less than 2019-01-01, but this may only result in customers that have booked once for a tour before 2019, I need to select people that are traveling at least once in 2017 and then at least once in 2018, but not in 2019.
select clientid from cust
where tour_date between '2017-01-01' and '2017-12-31'
and tour_date between '2018-01-01' and '2018-12-31'
and tour_date < '2019-01-01'
Any help would be appreciated, thanks.
Use correlated subquery with exists and not exists
select clientid from cust a
where exist
(select 1 from cust b where a.clientid=b.clientid and tour_date between '2017-01-01' and '2017-12-31')
and exist
(select 1 from cust b where a.clientid=b.clientid and tour_date between '2018-01-01' and '2018-12-31')
and not exists
(select 1 from cust b where a.clientid=b.clientid and tour_date between '2019-01-01' and '2019-12-31')
We could also try using aggregation here:
SELECT clientid
FROM cust
GROUP BY clientid
HAVING
COUNT(CASE WHEN tour_date BETWEEN '2017-01-01' AND '2017-12-31' THEN 1 END) > 0 AND
COUNT(CASE WHEN tour_date BETWEEN '2018-01-01' AND '2018-12-31' THEN 1 END) > 0 AND
COUNT(CASE WHEN tour_date < '2019-01-01' THEN 1 END) > 0;
Try this-
SELECT clientid
FROM
(
SELECT clientid,YEAR(tour_date) YR
FROM cust
WHERE YEAR(tour_date) IN (2017,2018)
)A
GROUP BY clientid
HAVING COUNT(DISTINCT YR) > 1
If you want clients and not the details of their trips, then use aggregation. I would phrase this as:
SELECT clientid
FROM cust
GROUP BY clientid
HAVING SUM(CASE WHEN tour_date >= '2017-01-01' AND tour_date < '2018-01-01' THEN 1 END) > 0 AND
SUM(CASE WHEN tour_date >= '2018-01-01' AND tour_date < '2019-01-01' THEN 1 END) > 0 AND
SUM(CASE WHEN tour_date >= '2019-01-01' AND tour_date < '2020-01-01' THEN 1 END) = 0 ;
Each condition in the HAVING clause is counting the number of tours during the year in question. The comparison > 0 says there is at least one; the = 0 says there are none during that year.

Using DB2 column alias within same select

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;

SQL Order by the sum of aliases

To preface, this is Microsoft SQL Server. I have several different columns of various earnings from different years. I need to order by the total sales of each given product, but not report it as an actual column. The commented line is how I tried to do it, but it seems you can't order by an alias. How would one go about this?
SELECT
StockItems.StockItemID,
StockItemName,
SUM(CASE WHEN OrderDate >= '2013-01-01'
AND OrderDate < '2014-01-01'
THEN Quantity * OrderLines.UnitPrice END) AS Sales2013,
SUM(CASE WHEN OrderDate >= '2014-01-01'
AND OrderDate < '2015-01-01'
THEN Quantity * OrderLines.UnitPrice END) AS Sales2014,
SUM(CASE WHEN OrderDate >= '2014-01-01'
AND OrderDate < '2015-01-01'
THEN Quantity * OrderLines.UnitPrice END) AS Sales2015,
SUM(CASE WHEN OrderDate >= '2015-01-01'
AND OrderDate < '2016-01-01'
THEN Quantity * OrderLines.UnitPrice END) AS Sales2016
FROM
Warehouse.StockItems
INNER JOIN Sales.OrderLines
ON Warehouse.StockItems.StockItemID = Sales.OrderLines.StockItemID
INNER JOIN Sales.Orders
ON Sales.OrderLines.OrderID = Sales.Orders.OrderID
GROUP BY
StockItems.StockItemID,
StockItemName
--ORDER BY SUM(Sales2013 + Sales2014 + Sales2015 + Sales2016)
Two methods
Put your query as inner query and order on it
put the full formula in order by
query for #1
select * from
(
SELECT
StockItems.StockItemID,
StockItemName,
SUM(CASE WHEN OrderDate >= '2013-01-01'
AND OrderDate < '2014-01-01'
THEN Quantity * OrderLines.UnitPrice END) AS Sales2013,
SUM(CASE WHEN OrderDate >= '2014-01-01'
AND OrderDate < '2015-01-01'
THEN Quantity * OrderLines.UnitPrice END) AS Sales2014,
SUM(CASE WHEN OrderDate >= '2014-01-01'
AND OrderDate < '2015-01-01'
THEN Quantity * OrderLines.UnitPrice END) AS Sales2015,
SUM(CASE WHEN OrderDate >= '2015-01-01'
AND OrderDate < '2016-01-01'
THEN Quantity * OrderLines.UnitPrice END) AS Sales2016
FROM
Warehouse.StockItems
INNER JOIN Sales.OrderLines
ON Warehouse.StockItems.StockItemID = Sales.OrderLines.StockItemID
INNER JOIN Sales.Orders
ON Sales.OrderLines.OrderID = Sales.Orders.OrderID
GROUP BY
StockItems.StockItemID,
StockItemName
) temp
order by SUM(Sales2013 + Sales2014 + Sales2015 + Sales2016)
query for #2
SELECT
StockItems.StockItemID,
StockItemName,
SUM(CASE WHEN OrderDate >= '2013-01-01'
AND OrderDate < '2014-01-01'
THEN Quantity * OrderLines.UnitPrice END) AS Sales2013,
SUM(CASE WHEN OrderDate >= '2014-01-01'
AND OrderDate < '2015-01-01'
THEN Quantity * OrderLines.UnitPrice END) AS Sales2014,
SUM(CASE WHEN OrderDate >= '2014-01-01'
AND OrderDate < '2015-01-01'
THEN Quantity * OrderLines.UnitPrice END) AS Sales2015,
SUM(CASE WHEN OrderDate >= '2015-01-01'
AND OrderDate < '2016-01-01'
THEN Quantity * OrderLines.UnitPrice END) AS Sales2016
FROM
Warehouse.StockItems
INNER JOIN Sales.OrderLines
ON Warehouse.StockItems.StockItemID = Sales.OrderLines.StockItemID
INNER JOIN Sales.Orders
ON Sales.OrderLines.OrderID = Sales.Orders.OrderID
GROUP BY
StockItems.StockItemID,
StockItemName
order by SUM(Quantity * OrderLines.UnitPrice)
SELECT StockItemID
, StockItemName
, Sales2013
, Sales2014
, Sales2015
, Sales2016
, Sales2013 + Sales2014 + Sales2015 + Sales2016 total_sales
FROM
(
SELECT
StockItems.StockItemID,
StockItemName,
SUM(CASE WHEN OrderDate >= '2013-01-01'
AND OrderDate < '2014-01-01'
THEN Quantity * OrderLines.UnitPrice END) AS Sales2013,
SUM(CASE WHEN OrderDate >= '2014-01-01'
AND OrderDate < '2015-01-01'
THEN Quantity * OrderLines.UnitPrice END) AS Sales2014,
SUM(CASE WHEN OrderDate >= '2014-01-01'
AND OrderDate < '2015-01-01'
THEN Quantity * OrderLines.UnitPrice END) AS Sales2015,
SUM(CASE WHEN OrderDate >= '2015-01-01'
AND OrderDate < '2016-01-01'
THEN Quantity * OrderLines.UnitPrice END) AS Sales2016
FROM
Warehouse.StockItems
INNER JOIN Sales.OrderLines
ON Warehouse.StockItems.StockItemID = Sales.OrderLines.StockItemID
INNER JOIN Sales.Orders
ON Sales.OrderLines.OrderID = Sales.Orders.OrderID
GROUP BY
StockItems.StockItemID,
StockItemName
)
ORDER BY total_sales
Add SUM column:
SUM(CASE WHEN OrderDate >= '2013-01-01'
AND OrderDate < '2016-01-01'
THEN Quantity * OrderLines.UnitPrice END) AS Sales_SUM
Then order by Sales_SUM
Well, the best performing solution would require to use a PIVOT, I wrap it in a CTE for better readability:
;WITH pvt AS (
SELECT
StockItems.StockItemID,
StockItemName,
YEAR(OrderDate) AS OrderYear,
Quantity * OrderLines AS SalesTotal,
SUM(Quantity * OrderLines) OVER (PARTITION BY StockItems.StockItemID) AS SalesForStockItemForYear
FROM
Warehouse.StockItems
INNER JOIN Sales.OrderLines
ON Warehouse.StockItems.StockItemID = Sales.OrderLines.StockItemID
INNER JOIN Sales.Orders
ON Sales.OrderLines.OrderID = Sales.Orders.OrderID
WHERE
YEAR(OrderDate) IN (2013,2014,2015,2016)
PIVOT (
SUM(SalesTotal) FOR OrderYear IN ([2013],[2014],[2015],[2016])
)
)
SELECT DISTINCT
pvt.StockItemID,
pvt.StockItemName,
pvt.[2013] as Sales2013,
pvt.[2014] as Sales2014,
pvt.[2015] as Sales2015,
pvt.[2016] as Sales2016
FROM
pvt
ORDER BY
pvt.SalesForStockItemForYear DESC

SubQuery accessing parent value

Hello all I am having a issue with this:
Select Customer_Tool_Lookup.ID,
Customer.CustomerName,
(select count(ID) as perDay
FROM CustomerData
WHERE DatetimeInserted >= '2013-04-29 00:00:00.000'
AND DatetimeInserted <= '2013-04-29 11:59:59.599'
AND Customer_ID = Customer_Tool_Lookup.Customer_ID) as DCount,
(select count(ID) as perMonth
FROM CustomerData
WHERE DatetimeInserted >= '2013-04-01 00:00:00.000'
AND DatetimeInserted <= '2013-04-30 11:59:59.599'
AND Customer_ID = Customer_Tool_Lookup.Customer_ID) as mCount,
(select count(ID) as perYear
FROM CustomerData
WHERE DatetimeInserted >= '2013-01-01 00:00:00.000'
AND DatetimeInserted <= '2013-04-30 11:59:59.599'
AND Customer_ID = Customer_Tool_Lookup.Customer_ID) as yCount,
Customer_tool_Lookup.PricePerClick,
Customer_Tool_lookup.MinimumPerMonth,
case
when ClicksPerMonth > (select count(ID) as perMonth
FROM CustomerData
WHERE DatetimeInserted >= '2013-04-01 00:00:00.000'
AND DatetimeInserted <= '2013-04-30 11:59:59.599'
AND Customer_ID = Customer_Tool_Lookup.Customer_ID)
then ClicksPerMonth
else ((select count(ID) as perMonth
FROM CustomerData
WHERE DatetimeInserted >= '2013-04-01 00:00:00.000'
AND DatetimeInserted <= '2013-04-30 11:59:59.599'
AND Customer_ID = Customer_Tool_Lookup.Customer_ID) - Customer_tool_lookup.MinimumPerMonth) * PricePerClick END as TDMonth
FROM Customer_tool_Lookup Left join Customer on Customer.ID = Customer_Tool_Lookup.Customer_ID
I am getting an error:
Invalid objectName 'Customer_tool_Lookup'
It started when I added the and statement at the end of the subquery:
AND Customer_ID = Customer_Tool_Lookup.Customer_ID <--
one each of them.
I normally don't ask SQL questions I have done subqueries before but for some reason I have trouble using parent data.
Thanks!
My suggestion would be to convert those correlated subqueries into a single subquery that you join to. If you use this subquery, then you can access the alias inside of your TDMonth CASE expression:
Select ctl.ID,
c.CustomerName,
cd.DCount,
cd.mCount,
cd.yCount
ctl.PricePerClick,
ctl.MinimumPerMonth,
case
when ClicksPerMonth > cd.mCount
then ClicksPerMonth
else (cd.mCount - ctl.MinimumPerMonth) * PricePerClick
END as TDMonth
from Customer_tool_Lookup ctl
left join Customer c
on c.ID = ctl.Customer_ID
left join
(
select Customer_ID,
COUNT(case
when DatetimeInserted >= '2013-04-29 00:00:00.000'
and DatetimeInserted <= '2013-04-29 11:59:59.599'
then ID end) as DCount,
COUNT(case
when DatetimeInserted >= '2013-04-01 00:00:00.000'
and DatetimeInserted <= '2013-04-30 11:59:59.599'
then ID end) as mCount,
COUNT(case
when DatetimeInserted >= '2013-01-01 00:00:00.000'
and DatetimeInserted <= '2013-04-30 11:59:59.599'
then ID end) as yCount
from CustomerData
group by Customer_ID
) cd
on ctl.Customer_ID = cd.Customer_ID