How can I use a new created column in GROUP BY - sql

In my SQL query, I want to check if a column has the string 'test' and safe the value in a new column
When I use the new column in GROUP BY, I get error saying it can't find the new column:
SELECT
CAST([EvtTime] as date) AS myDay,
CASE WHEN [result] LIKE '%test%' THEN 1 ELSE 0 END AS testResult,
COUNT_BIG(*) AS myCount,
[name]
FROM [mytable]
GROUP BY myDay, testResult
I am using SQL Server.

CROSS APPLY is a clean way to solve this issue.
SELECT
CAST([EvtTime] as date) AS myDay,
X.testResult,
COUNT_BIG(*) AS myCount,
[name]
FROM myTable
CROSS APPLY (VALUES (CASE WHEN [result] LIKE '%test%' THEN 1 ELSE 0 END)) AS X(testResult)
GROUP BY myDay, testResult

You can use inline view:
SELECT *,
COUNT_BIG(*) AS myCount
FROM (
SELECT
CAST([EvtTime] as date) AS myDay,
CASE WHEN [result] LIKE '%test%' THEN 1 ELSE 0 END AS testResult,
[name]
FROM [MyTable]
) MyInlineView
GROUP BY myDay, testResult

Related

Recursive CTE Pivot for rolling count in SQL Server?

Basically I have a table of membership dates and status changes and I want to create a rolling count of each number of members by status for each date like:
And I want to output it like:
Not really sure on the best way to construct this query I suppose I'd have to create a recursive query to count the events at the date and then pivot the output to create separate columns for the member status?
TIA
create table MyTable(status int,st datetime, memberID int)
insert into MyTable values(1,'2022-02-01',1),
(1,'2022-03-01' ,2),
(2,'2022-04-01',1)
select [st],[1],[2]
from (select [st],memberID,status from MyTable) as SrcTable
pivot(
count(memberID) for status in ([1],[2])
) as pivottable
order by [st] asc
But it doesnt aggregate in March like I want it to
Figured it out I put the last date as get_date() since that what my problem in real-life requires but I did make use of a recursive CTE and pivot
create table MyTable(status int,st datetime, memberID int)
insert into MyTable values(1,'2022-02-01',1),
(1,'2022-03-01' ,2),
(2,'2022-04-01',1);
with cte as (
select status,st,memberID,(case when Nxt_sts is null then 0 else Nxt_sts end)
as Nxt_sts,
(case when Nxt_st is null then FORMAT(DateAdd(Month,1,getdate()), 'yyyyMM01')
else Nxt_st end) as Nxt_st
from (select
A.status,A.st,A.memberID,B.status as Nxt_sts,B.st as nxt_st
from MyTable A
left join MyTable B
on A.MemberID = B.MemberID
and A.status+1 = B.status ) A
)
, cte_2 as
(
select status,st,memberID,Nxt_sts,Nxt_st
from cte
Union All
select status,DateAdd(Month, 1 ,st),memberID,Nxt_sts,Nxt_st from cte_2
where DateAdd(Month, 1 ,st) < Nxt_st
)
select [st],[1],[2],[3]
from (select [st],memberID,status from cte_2) as SrcTable
pivot(
count(memberID) for status in ([1],[2],[3])
) as pivottable
order by [st] asc

Select statement with a condition on multiple entries

Following is my table:
I want to create a view with the following conditions in a select statement:
If count(employee_id) > 1 then only the record having status = 'Current' is picked in the view.
I tried:
select employee_id
, case when COUNT(employee_id) > 1 and statusval = 'Current' then 'Y' else 'N' end as val
from table1
group by employee_id
I hope someone can help me with this statement. Thanks.
Try this
DECLARE #T TABLE (ID INT, STATUS VARCHAR(50))
INSERT INTO #T VALUES (1,'Current'),(2,'Historical'),(2,'Historical'),(2,'Current')
SELECT * FROM #T M
INNER JOIN (SELECT ID FROM #T
GROUP BY ID
HAVING COUNT(ID) > 1) S ON S.ID=M.ID
WHERE M.STATUS = 'Current'
Just to show you how your attempt could have looked. You were nearly there, you just needed to use the windowed version of count e.g.
with cte as (
select Employee_Id, [Status]
, case when count(*) over (partition by id) > 1 and [Status] = 'Current' then 1 else 0 end Val
from Table1
)
select Employee_Id, [Status]
from cte
where Val = 1;
And this approach appears on the face of it to perform better than a join.
All of your sample data have exactly one row with 'Current'. So, the simplest solution appears to be:
select t.*
from t
where t.status = 'Current';

How pivot a sum of values

i have a question, How can i pivot an aggregation result to look like ..
I'm trying to pivot a simple aggregation using this query first:
select sync_action action, count(sync_action) total
FROM my_table
group by sync_action
and to pivot the table i'm using:
select * from (
select sync_action , count(sync_action) total
FROM my_table
group by sync_action )
pivot
(
count(sync_action)
for sync_action in ('delete','create')
)
;
and i don't know where is the error, because the result is:
the idea is have the same as the first image.
Can somebody help me?
Best regards
I would just use conditional aggregation:
select
sum(case when sync_action = 'delete' then total else 0 end) sum_delete,
sum(case when sync_action = 'create' then total else 0 end) sum_create
from mytable
where sync_action in ('delete', 'create')
You don't need to do group by, just do like
SELECT *
FROM mytable
pivot
( COUNT(sync_action)
FOR sync_action IN('delete','create')
);
In your query you need "SUM of total" instead of "Count of sync_action" in pivot section. Others are ok. If you use count, in your case you will always get 1.
select * from (
select sync_action , count(sync_action) total
FROM my_table
group by sync_action ) as p
pivot
(
sum(p.total)
for p.sync_action in ("delete","create")
)pt
I think you just want:
select sum(case when sync_action = 'delete' then 1 else 0 end) as delete,
sum(case when sync_action = 'create' then 1 else 0 end) as create
from my_table;
I don't see how pivot helps at all with what you want to do.

SQL - WHERE on new column

I've a table with 3 columns: Id, Price, Total.
I'm writing this sql statement:
SELECT Id, Price, Total,
CASE WHEN [Total] IS NULL THEN '0'
WHEN [Total] IS NOT NULL '1'
ELSE ''
END AS NewColumnName
FROM Table
If I run this sql, I have no error. But if I add a Where, like this:
WHERE NewColumnName= '1' the server return an error: the name of column NewColumnName is not valid.
Please help me!
Thanks a lot!!
RM
Can you try this way?
select *
from (
SELECT Id, Price, Total,
CASE WHEN [Total] IS NULL THEN '0'
WHEN [Total] IS NOT NULL '1'
ELSE ''
END AS NewColumnName
FROM Table
) x
where
NewColumnName= '1'
Try this,
SELECT Id, Price, Total,
CASE WHEN [Total] IS NULL THEN '0'
WHEN [Total] IS NOT NULL '1'
END AS NewColumnName
FROM Table
WHERE CASE WHEN [Total] IS NULL THEN '0'
WHEN [Total] IS NOT NULL '1'
END = '1'
Generally use a subquery,
SELECT Id, Price, Total, NewColumnName
FROM (
SELECT
Id,
Price,
Total,
CASE
WHEN [Total] IS NULL THEN '0'
ELSE '1'
END [NewColumnName]
FROM
Table) [WithNew]
WHERE
NewColumnName = '1';
or in your case you could do,
SELECT
Id,
Price,
Total,
1 [NewColumnName]
FROM
Table
WHERE
Total IS NOT NULL;
USE [AdventureWorks2012]
WITH cte as (
SELECT [AddressID], [AddressLine1]
, CASE WHEN [City] = 'Bothell' THEN 1 ELSE 0 END AS [NewColumn]
FROM Person.Address )
SELECT * FROM CTE
WHERE [NewColumn] = 1
So yours would be re-written like this:
WITH cte as (
SELECT Id, Price, Total,
CASE WHEN [Total] IS NULL THEN '0'
WHEN [Total] IS NOT NULL '1'
ELSE ''
END AS NewColumnName
FROM Table)
SELECT * FROM CTE where [NewColumnName] = 1
You can't use NewColumnName in the WHERE Clause. You will have to use the CASE statement again in WHERE Clause or do what #Lajos suggested.
You can just write your query like this:
SELECT Id, Price, Total,
FROM Table
WHERE Total IS NOT NULL
That's doing the same thing, except without the case statement.

IF clause in SQL from statement

I need a temporary solution to a problem I've created. Essentially I want to calculate two values, but use a different method dependant on the result of a condition.
select userReturnval, userregisterid, OtherValue
FROM
(
(SELECT otherValue
FROM...
) as tblO --unrelated table
,
(
if (select count(userregisterid) from table1 where site =#siteID and userid=#userID) >0
SELECT userReturnval, userregisterid
FROM
(
SELECT userReturnval, userregisterid, Rank() OVER (PARTITION BY .. ORDER BY ...) as RANK
FROM ...
WHERE --first where clause
) as tblRank
WHERE (RANK =1)
else
SELECT userReturnval, userregisterid
FROM
(
SELECT userReturnval, userregisterid, Rank() OVER (PARTITION BY .. ORDER BY ...) as RANK
FROM ...
WHERE --different where clause
) as tblRank
WHERE (RANK =1)
) as tblR
My if works fine on its own, I just to get it working as part of the larger query. At the moment, sqlserver doesn't like the if being in there.
Hopefully someone can point me in the right direction!
You can try using case statements in the WHERE clause, something like the statement below. Note that I don't think this will be particularly optimal for performance.
Doing it like this does allow you to keep it to a single statement though:
select userReturnval, userregisterid, OtherValue
FROM
(
(SELECT otherValue
FROM...
) as tblO --unrelated table
,
(
SELECT userReturnval, userregisterid
FROM
(
SELECT userReturnval, userregisterid, Rank() OVER (PARTITION BY .. ORDER BY ...) as RANK
FROM ...
WHERE
case --Choose which where clause to use
when (select count(userregisterid) from table1 where site =#siteID and userid=#userID) >0 then
case when /*First where clause*/ then 1
else 0
end
else
case when /*Second where clause*/ then 1
else 0
end
end
= 1
) as tblRank
WHERE (RANK =1)
) as tblR