Getting error Invalid column name days in sql server - sql

I am working on sql query, When i run the query i am getting error Invalid column name 'days'., Can anyone please help me, why i am getting error like this, it looks like there something issue with having, but still not able to resolve it, here is my query
SELECT
COUNT(*) AS total
FROM
(
SELECT *, ABS(DATEDIFF(day, GETDATE(), EpStart)) AS [days]
FROM tb_Episode
HAVING [days] <= ''
) AS episodes
WHERE
(episodes.EOEClaimDate is NULL or episodes.EOEClaimDate = '0000-00-00') AND
episodes.PayerType = 'Ep' AND
episodes.EpEnd < '2018-02-05' AND
episodes.CustID = '27'

You can't use in HAVING clause the alias of your field.
Why you use HAVING instead of WHERE?
The same restriction for HAVING exists for WHERE,
So your query will become:
FROM
(
SELECT *, ABS(DATEDIFF(day, GETDATE(), EpStart)) AS [days]
FROM tb_Episode
WHERE ABS(DATEDIFF(day, GETDATE(), EpStart)) <= ''
) AS episodes

According to this answer by #Codo you cannot using a HAVING on an alias/virtual column as each SQL clause is performed in a designated order
FROM clause
WHERE clause
GROUP BY clause
HAVING clause
SELECT clause
ORDER BY clause
So because your column alias is defined after the HAVING clause you get the invalid column name error as the column doesn't technically exist yet.

Related

SQL: Filter records based on record creation date and other criteria

I am struggling to find a better solution to pick unique records from my user call data table.
My table structure is as follows:
SELECT [MarketName],
[WebsiteName] ,
[ID] ,
[UserID],
[CreationDate],
[CallDuration],
[FromPhone] ,
[ToPhone],
[IsAnswered],
[Source]
FROM [dbo].[UserCallData]
There are multiple entries in this table with different and same ID's. I wanted to check if [FromPhone] and [ToPhone] exists multiple times within last 3 months, if yes, I wanted to pick the first record with all columns based on [CreationDate], count the number of occurrences as TotalCallCount and sum the totalCallDuration as a single record. If [FromPhone] and [ToPhone] does not occur multiple times, I wanted to pick all columns as such. I have been able to put up partial query like below. But this doesn't return all columns without including in group by clause and also it doesn't satisfy my entire criteria. Any help on this would be highly appreciated.
select [FromPhone],
MIN([CreationDate]),
[ToPhone],
marketname,
count(*) as TotalCallCount ,
sum(CallDuration) as TotalCallDuration
from [dbo].[UserCallData]
where [CreationDate] >= DATEADD(MONTH, -3, GETDATE())
group by [FromPhone],[ToPhone], marketname
having count([FromPhone]) > 1 and count([ToPhone]) >1
Try to use ROW_NUMBER()
;with cte as
(
select *, ROW_NUMBER() OVER(PARTITION BY FromPhone, ToPhone ORDER BY CreationDate) as RN
from UserCallData
where CreationDate >= DATEADD(MONTH, -3, GETDATE())
),
cte_totals as
(
select C1.FromPhone, C1.ToPhone, COUNT(*) as TotalCallCount, SUM(CallDuration) as TotalCallDuration
from cte C1
where exists(select * from cte C2 where C1.FromPhone = C2.FromPhone and C1.ToPhone = C2.ToPhone and C2.RN > 1)
group by C1.FromPhone, C1.ToPhone
)
select C1.*, TotalCallCount, TotalCallDuration
from cte C1
inner join cte_totals C2 on C1.FromPhone = C2.FromPhone and C1.ToPhone = C2.ToPhone
where C1.RN = 1
I wrote query right in here so it can have some mistakes or mistypes, but the main idea might be clear.
I'm not entirely sure I've understood the question, but if I have the following may be what you want (or be a useful starting point):
SELECT
ucd.FromPhone,
min(ucd.CreationDate) as MinCreationDate,
ucd.ToPhone,
ucd.MarketName,
count(*) as TotalCallCount,
sum(ucd.CallDuration) as TotalCallDuration,
case
when min(ucd.WebsiteName) = max(ucd.WebsiteName) then min(ucd.WebsiteName)
else '* Various'
end as WebsiteName,
case
when min(ucd.ID) = max(ucd.ID) then min(ucd.ID)
else '* Various'
end as ID,
case
when min(ucd.UserID) = max(ucd.UserID) then min(ucd.UserID)
else '* Various'
end as UserID,
case
when min(ucd.IsAnswered) = max(ucd.IsAnswered) then min(ucd.IsAnswered)
else '* Some'
end as IsAnswered,
case
when min(ucd.Source) = max(ucd.Source) then min(ucd.Source)
else '* Various'
end as Source
FROM
dbo.UserCallData ucd
WHERE
ucd.CreationDate >= DATEADD(MONTH, -3, GETDATE())
GROUP BY
ucd.FromPhone,
ucd.ToPhone,
ucd.MarketName
Where we are collapsing rows together, if all the rows agree on a given column (so min(Field) = max(Field)), I return the min(Field) value (which is the same all the others, but avoid problems with needing additional "group by" clauses which would interfere with the other cases). Where they don't all agree, I've returned "* something".
The code assumes that all the columns are text type columns (you haven't said), you may get conversion errors. It also assumes that none of these fields are null. You / we can adapt the code if those assumptions aren't correct. If you aren't able to do that for yourself, let me know about issues, I'll be happy to do what I can.

How to perform arithmetic on a column defined on a SELECT statement

SELECT DATEDIFF(MINUTE, j.start_time , j.end_time) as job_duration,
(jtype.cost_per_minute * job_duration) as job_cost
All the joins and from statements are done it runs without error when there is no arithmetic to be done but with the multiplication it gives an error. Not sure what to do. Any help would be appreciated thanks in advance.
Invalid column name 'job_duration'
job_duration does not exist until the query gets executed you can do it by nesting into another sql clause or by doing this:
SELECT DATEDIFF(MINUTE, j.start_time , j.end_time) AS job_duration, (jtype.cost_per_minute * DATEDIFF(MINUTE, j.start_time , j.end_time)) AS 'job_cost'
Another way to write that statement:
;with _CTE as
(
SELECT YourJobId, DATEDIFF(MINUTE, start_time , end_time) AS job_duration
from YourTableName
)
Select jtype.cost_per_minute * _CTE.job_duration AS 'job_cost'
from YourTableName as jType
inner join _CTE on jtype.YourJobId = _CTE.YourJobId

SQL Subquery using IN Statment with coalesce

I have the following SELECT statmentment
SELECT
UserID
,UserName
,TradingParty
,Email
,[PrivDesc]
,LastLogin
,IsApproved
FROM
cte_getAll allUsers
WHERE
allUsers.TradingParty = COALESCE(#TradingParty, allUsers.TradingParty)
AND allUsers.Username = COALESCE(#Username, allUsers.Username)
AND allUsers.Email = COALESCE(#EmailAddress, allUsers.Email)
AND DATEADD(dd, DATEDIFF(dd, 0, allUsers.[LastLogin]), 0) >= COALESCE(#FromDate, DATEADD(dd, DATEDIFF(dd, 0, allUsers.[LastLogin]), 0))
AND DATEADD(dd, DATEDIFF(dd, 0, allUsers.[LastLogin]), 0) <= COALESCE( #ToDate, DATEADD(dd, DATEDIFF(dd, 0, allUsers.[LastLogin]), 0))
AND allUsers.IsApproved = COALESCE(#AccountActive, allUsers.IsApproved)
AND allUsers.[PrivId] -- IN (SELECT privId from #selectedPriv)
IN (COALESCE((SELECT PrivID FROM #selectedPriv), allUsers.[PrivId]))
EDIT
Prior to this statment i am populating the #selectedPriv temp table according to the users input. If there is not user input therefore the table will contain nothin
On the final AND statement i am trying to find all data where privId is equal to a list of privs which the user has entered. So for example the user eneters 1,2,3,4,5,6 that is stored into a temp table, from this i need to find all the rows from my original table which are associated with these priv.
Here is my issue if i use the commented IN statement it works but since the user is allowed to pass in NULL i need it within a COALESCE, but when i do this i get the message
Subquery returned more than 1 value. This is not permitted when the
subquery follows =, !=, <, <= , >, >= or when the subquery is used as
an expression.
I havent got a clue on why this is. Any ideas that will help me fix this issue?
If I understand your question correctly, you have a table variable that has values that you want to select from, but if they don't have any values in the table, you don't want the restriction at all.
The reason you're getting the error you're getting is due to COALESCE() only expecting a single value to transform, but your query is returning multiple.
This may be what you're looking for:
AND
(
NOT EXISTS (SELECT * FROM #selectedPriv WHERE PrivID IS NOT NULL)
OR
(
EXISTS (SELECT * FROM #selectedPriv WHERE PrivID IS NOT NULL)
AND allUsers.[PrivId] IN (SELECT PrivID FROM #selectedPriv)
)
)
Since you are populating the temp table #selectedPriv prior to this statement just add an else there -- if the input is null have #selectedPriv =
SELECT DISTINCT PrivId FROM cte_getAll
This should be faster than a more complicated where statement that checks count(*) in #selectedPriv which is the other way to do it.
COALESCE can only take one value for it's first argument, which is why it complains when you get more than one value from that query. You could switch that part for something a bit different using some ANDs and ORs. (Note: untested, but should at least be close.)
AND (((select count(*) from #selectedPriv) = 0)
OR ((select count(*) from #selectedPriv) != 0 AND allUsers.[PrivId] IN (SELECT privId from #selectedPriv)))
coalesce works fine but you can use ORs instead and that might help you with your last AND.
SELECT
UserID,
UserName,
TradingParty,
Email,
[PrivDesc],
LastLogin,
IsApproved
FROM
cte_getAll allUsers
WHERE
allUsers.TradingParty = COALESCE(#TradingParty,allUsers.TradingParty)
AND (#Username IS NULL OR allUsers.Username = #Username)
AND (#EmailAddress IS NULL OR allUsers.Email = #EmailAddress)
AND (#FromDate IS NULL OR DATEADD(dd,DATEDIFF(dd,0,allUsers.[LastLogin]),0) >= #FromDate)
AND (#ToDate IS NULL OR DATEADD(dd,DATEDIFF(dd,0,allUsers.[LastLogin]),0) <= #ToDate)
AND (#AccountActive IS NULL OR allUsers.IsApproved = #AccountActive)
AND (#PrivIDS IS NULL OR allUsers.[PrivId] IN (SELECT PrivID FROM #selectedPriv))

SQL subquery in the AND statement

A couple problems.
Solved valid_from_tsp <> max(valid_from_tsp) - how can I get my query to filter based on not being the max date? This idea doesn't work The error being returned is: "Improper use of an aggregate function in a WHERE clause"
My second issue is when I run it without the date, I am returned a syntax error: Syntax error, expected something like 'IN' keyword or 'CONTAINS' keyword between ')' and ')'
What do you see that I don't? Thanks in advance
Edited Query
select
a.*,
b.coverage_typ_cde as stg_ctc
from P_FAR_BI_VW.V_CLAIM_SERVICE_TYP_DIM a
inner join (select distinct etl_partition_id, coverage_typ_cde from
P_FAR_STG_VW.V_CLAIM_60_POLICY_STG where row_Create_tsp > '2013-11-30 23:23:59')b
on (a.etl_partition_id = b.etl_partition_id)
where a.valid_from_tsp > '2013-11-30 23:23:59'
and a.coverage_typ_cde = ' '
and (select * from P_FAR_SBXD.T_CLAIM_SERVICE_TYP_DIM where service_type_id = 136548255
and CAST(valid_from_tsp AS DATE) <> '2014-03-14')
Trouble part: and (select * from P_FAR_SBXD.T_CLAIM_SERVICE_TYP_DIM where service_type_id = 136548255
and CAST(valid_from_tsp AS DATE) <> '2014-03-14')
I am trying to filter by the date on the service_type_id, and I am getting the error in question 2
As for sample data: This is kinda tricky, This query returns many thousands of rows of data. Currently when I do the inner join, I get a secondary unique index violation error. So I am trying to filter out everything but the more recent which could be under that violation (service_type_id is the secondary index)
If I bring back three rows with the service_type_id with three different valid_from_tsp timestamps, I only want to keep the newest one, and in the query, not return the other two.
I don't know about your second question, but your first error is due to using an aggregate function max in a where clause. I'm not really sure what you want to do here, but a quick fix is to replace max(valid_from_tsp) with a subquery that only returns the maximum value.
This is your query:
select a.*, b.coverage_typ_cde as stg_ctc
from P_FAR_BI_VW.V_CLAIM_SERVICE_TYP_DIM a inner join
(select distinct etl_partition_id, coverage_typ_cde
from P_FAR_STG_VW.V_CLAIM_60_POLICY_STG
where row_Create_tsp > '2013-11-30 23:23:59'
) b
on (a.etl_partition_id = b.etl_partition_id)
where a.valid_from_tsp > '2013-11-30 23:23:59' and
a.coverage_typ_cde = ' ' and
(select *
from P_FAR_SBXD.T_CLAIM_SERVICE_TYP_DIM
where service_type_id = 136548255 and
CAST(valid_from_tsp AS DATE) <> '2014-03-14'
);
In general, you cannot have a subquery just there in the where clause with no condition. Some databases might allow a scalar subquery in this context (one that returns one row and one column), but this isn't a scalar subquery. You can fix the syntax by using exists:
where a.valid_from_tsp > '2013-11-30 23:23:59' and
a.coverage_typ_cde = ' ' and
exists (select 1
from P_FAR_SBXD.T_CLAIM_SERVICE_TYP_DIM
where service_type_id = 136548255 and
CAST(valid_from_tsp AS DATE) <> '2014-03-14'
);

Help with SQL CASE Statement in SELECT Query

Here is my SQL statement:
SELECT [Item], SUM([Quantity]) AS SumOfQuantity, SUM([Price Each]) AS SumOfTotal,
([SumOfTotal] / [SumOfQuantity]) As Average,
CASE
WHEN [Average] <= 6 THEN SumOfTotal
ELSE 6*[SumOfQuantity] END AS GrossComm
FROM Data
GROUP BY [Item];
When I try to execute this query, I get the error message:
Syntax error (missing operator) in query expression 'CASE WHEN [Average] <= 6 THEN SumOfTotal ELSE 6*[SumOfQuantity] END AS GrossComm
Any ideas?
Thanks!
You can't reference a derived field by name in the CASE statement. Instead of [average] use the formulas.
You actually may have a larger issue since all your fields are based on other derived fields, so you might have to write out the formula for each one multiple times.
It's likely there is also an issue with your other fields that the CASE is obscuring. Basically don't refer to a calculated/aliased field in the same query by name, since it won't work.
If this is SQL Server you COULD do a workaround using a CTE:
;WITH CTE AS
(
SELECT [Item], SUM([Quantity]) AS SumOfQuantity, SUM([Price Each]) AS SumOfTotal,
FROM Data
GROUP BY [Item]
)
SELECT *, ([SumOfTotal] / [SumOfQuantity]) As Average,
CASE
WHEN ([SumOfTotal] / [SumOfQuantity]) <= 6 THEN SumOfTotal
ELSE 6*[SumOfQuantity] END AS GrossComm
FROM CTE