Trying to group by a value in SQL - sql

I have a table called TESTTABLE
The table script and some sample date
CREATE TABLE Test_Table(
NODE VARCHAR(10) NOT NULL PRIMARY KEY
,EVENTID CHAR(255) NOT NULL
,TYPE INTEGER NOT NULL
,FIRSTOCCURRENCE VARCHAR(16) NOT NULL
,LASTOCCURRENCE VARCHAR(16) NOT NULL
,TALLY INTEGER NOT NULL
,TICKETNUMBER VARCHAR(20)
,TIME_DELTA VARCHAR(5)
);
INSERT INTO Test_Table(NODE,EVENTID,TYPE,FIRSTOCCURRENCE,LASTOCCURRENCE,TALLY,TICKETNUMBER,TIME_DELTA) VALUES ('Washington','ReachabilityProblem',2,'12/13/2017 23:24','12/13/2017 23:24',1,NULL,'1 sec');
INSERT INTO Test_Table(NODE,EVENTID,TYPE,FIRSTOCCURRENCE,LASTOCCURRENCE,TALLY,TICKETNUMBER,TIME_DELTA) VALUES ('San Diego','ReachabilityProblem',1,'12/13/2017 23:23','12/13/2017 23:23',1,NULL,NULL);
INSERT INTO Test_Table(NODE,EVENTID,TYPE,FIRSTOCCURRENCE,LASTOCCURRENCE,TALLY,TICKETNUMBER,TIME_DELTA) VALUES ('Richmond','ReachabilityProblem',1,'12/13/2017 14:23','12/13/2017 14:23',1,NULL,NULL);
INSERT INTO Test_Table(NODE,EVENTID,TYPE,FIRSTOCCURRENCE,LASTOCCURRENCE,TALLY,TICKETNUMBER,TIME_DELTA) VALUES ('Richmond','ReachabilityProblem',1,'12/13/2017 23:23','12/13/2017 23:23',1,NULL,NULL);
INSERT INTO Test_Table(NODE,EVENTID,TYPE,FIRSTOCCURRENCE,LASTOCCURRENCE,TALLY,TICKETNUMBER,TIME_DELTA) VALUES ('New York','ReachabilityProblem',2,'12/13/2017 23:24','12/13/2017 23:24',1,NULL,'1 sec');
INSERT INTO Test_Table(NODE,EVENTID,TYPE,FIRSTOCCURRENCE,LASTOCCURRENCE,TALLY,TICKETNUMBER,TIME_DELTA) VALUES ('New York','ReachabilityProblem',2,'12/13/2017 11:32','12/13/2017 11:33',2,NULL,'1 sec');
INSERT INTO Test_Table(NODE,EVENTID,TYPE,FIRSTOCCURRENCE,LASTOCCURRENCE,TALLY,TICKETNUMBER,TIME_DELTA) VALUES ('New York','ReachabilityProblem',1,'12/13/2017 16:35','12/13/2017 16:35',1,NULL,NULL);
INSERT INTO Test_Table(NODE,EVENTID,TYPE,FIRSTOCCURRENCE,LASTOCCURRENCE,TALLY,TICKETNUMBER,TIME_DELTA) VALUES ('Landsdown','ReachabilityProblem',2,'12/13/2017 23:24','12/13/2017 23:24',1,NULL,'1 sec');
INSERT INTO Test_Table(NODE,EVENTID,TYPE,FIRSTOCCURRENCE,LASTOCCURRENCE,TALLY,TICKETNUMBER,TIME_DELTA) VALUES ('Houston','ReachabilityProblem',2,'12/13/2017 14:24','12/13/2017 14:24',1,NULL,'1 sec');
INSERT INTO Test_Table(NODE,EVENTID,TYPE,FIRSTOCCURRENCE,LASTOCCURRENCE,TALLY,TICKETNUMBER,TIME_DELTA) VALUES ('Houston','ReachabilityProblem',1,'12/13/2017 11:31','12/13/2017 11:32',2,NULL,NULL);
INSERT INTO Test_Table(NODE,EVENTID,TYPE,FIRSTOCCURRENCE,LASTOCCURRENCE,TALLY,TICKETNUMBER,TIME_DELTA) VALUES ('Dallas','ReachabilityProblem',1,'12/13/2017 23:23','12/13/2017 23:23',1,NULL,NULL);
INSERT INTO Test_Table(NODE,EVENTID,TYPE,FIRSTOCCURRENCE,LASTOCCURRENCE,TALLY,TICKETNUMBER,TIME_DELTA) VALUES ('Dallas','ReachabilityProblem',2,'12/13/2017 23:24','12/13/2017 23:24',1,NULL,'1 sec');
INSERT INTO Test_Table(NODE,EVENTID,TYPE,FIRSTOCCURRENCE,LASTOCCURRENCE,TALLY,TICKETNUMBER,TIME_DELTA) VALUES ('Coco Beach','ReachabilityProblem',1,'12/13/2017 23:23','12/13/2017 23:23',1,NULL,NULL);
I'm trying to obtain this
I have tried this
Select DATEDIFF(Day, GETDATE(), DATEADD(HOUR, 15, GETDATE()))
Select
[NODE]
,[EVENTID]
,[TYPE]
,[FIRSTOCCURRENCE]
,LASTOCCURRENCE]
,DATEDIFF(Minute, FIrst OCCURENCE, LAST OCCURENCE) as [Outage in MIN]
,[TicketNumber]
,[Severity]
,Tally]
From
[XYZ].[XYZ].[XYZ_STATUS]
Where
[FIRST OCCURRENCE] >= DATEADD(hh, -24, GETDATE())
Group by node;
Please help a rookie

Group by returns a relation/table with a row for each group, if you are going to use the GROUP BY clause, so in your SELECT statement you can only select the column that you are grouping by and use aggregate functions on that column because the other columns will not appear in the resulting table.
Maybe this is what you want...
Select
DATEDIFF (DAY, GETDATE(), DATEADD(Hour, 15, GETDATE())),
,Node
,EventID
,Type
,Severity
,Tally
FROM xyz.xyz.xyz_status
GROUP BY Node,EventID,Type,Severity,Tally
When we group by two or more columns, it is saying "Group them so that all of those with the same col1 and col2 are in the same group, and then calculate all the aggregate functions (Count, Sum, Average, etc.) for each of those groups"
Maybe you want this...
SELECT DATEDIFF(minute,(SELECT TOP(1) FIRSTOCCURRENCE FROM
xyz.xyz.xyz_status),(SELECT TOP(1) LASTOCCURRENCE FROM
xyz.xyz.xyz_status))
FROM xyz.xyz.xyz_status
WHERE node = 'Houston';
Here you can take a look at more examples of DATEDIFF function.

This should put you on track although Writing reports in SQL is probably a bad idea. What I believe you're wanting to do it output. You can also look at the ROLLUP options some of which are deprecated.
with data as (
select
NODE, EVENTID, TYPE, FIRSTOCCURRENCE, LASTOCCURRENCE,
DATEDIFF(Minute, FIRSTOCCURRENCE, LASTOCCURRENCE) as OutageInMin,
TicketNumber, Tally,
ROW_NUMBER() OVER (PARTITION BY NODE ORDER BY FIRSTOCCURRENCE) as rn
from Test_Table
--WHERE FIRSTOCCURRENCE >= DATEADD(hh, -24, GETDATE())
)
select
case when grouping(rn) = 1 then 'SITE TOTAL' else NODE end as NODE,
case when grouping(rn) = 1 then null else min(EVENTID) end as EVENTID,
case when grouping(rn) = 1 then null else min(TYPE) end as TYPE,
case when grouping(rn) = 1 then null else min(FIRSTOCCURRENCE) end as FIRSTOCCURRENCE,
case when grouping(rn) = 1 then null else min(LASTOCCURRENCE) end as LASTOCCURRENCE,
case when grouping(rn) = 1 then null else min(Tally) end as Tally,
case when grouping(rn) = 1 then null else min(TicketNumber) end as TicketNumber,
case when grouping(node) = 1
then min(OutageInMin) else sum(OutageInMin) end as "Outage In MIN"
from
data
group by grouping sets ( (NODE, rn), (NODE) )
order by data.NODE, grouping(rn), rn;
http://rextester.com/DZIHJ81264

GROUP BY is only authorized in SQL when you are aggregating something. The easiest exemple is a count.
Example : you want to know how much EventID are linked to a given Node :
SELECT Count(EventId), node FROM xyz.xyz.xyz_status GROUP BY node;
Here is a site that present the Group By function. If you clarify what you are searching for, we'll give you a more concrete example.

Related

Counting number of transactions within past 1 hour on a particular user

Is there any way how to (in the best case, without using cursor) count number of transactions that the same user made in previous 1 hour.
That means that for this table
CREATE TABLE #TR (PK INT, TR_DATE DATETIME, USER_PK INT)
INSERT INTO #TR VALUES (1,'2018-07-31 06:02:00.000',10)
INSERT INTO #TR VALUES (2,'2018-07-31 06:36:00.000',10)
INSERT INTO #TR VALUES (3,'2018-07-31 06:55:00.000',10)
INSERT INTO #TR VALUES (4,'2018-07-31 07:10:00.000',10)
INSERT INTO #TR VALUES (5,'2018-07-31 09:05:00.000',10)
INSERT INTO #TR VALUES (6,'2018-07-31 06:05:00.000',11)
INSERT INTO #TR VALUES (7,'2018-07-31 06:55:00.000',11)
INSERT INTO #TR VALUES (8,'2018-07-31 07:10:00.000',11)
INSERT INTO #TR VALUES (9,'2018-07-31 06:12:00.000',12)
The result should be:
The solution could be something like: COUNT(*) OVER (PARTITION BY USER_PK ORDER BY TR_DATE ROWS BETWEEN ((WHERE DATEADD(HH,-1,PRECENDING.TR_DATE) > CURRENT ROW.TR_DATE) AND CURRENT ROW ...but I know that ROWS BETWEEN can not be used like that...
I am guessing SQL Server based on the syntax. In SQL Server, you can use apply:
select t.*, tr2.result
from #tr tr outer apply
(select count(*) as result
from #tr tr2
where tr2.user_id = tr.user_id and
tr2.tr_date > dateadd(hour, -1, tr.date) and
tr2.tr_date <= tr.tr_date
) tr2;
SELECT USER_PK, COUNT(*) AS TransactionCount
FROM #TR
WHERE DATEDIFF(MINUTE, TR_DATE, GETDATE()) <= 60
AND DATEDIFF(MINUTE, TR_DATE, GETDATE()) >= 0
GROUP BY USER_PK
You can change GETDATE() with whatever you want, but they need to have the same value

SQL windowed function/rownum/order by

I'm trying to see how often a customer has requested Re-Activation of their Internet account.
The problem is, we capture a limited set of data to group on. So my data set is below.
I am trying to Count from the first time a Re-Activation request was created until the First time it was COMPLETED, once it has been completed finish the count of days it took for the request to complete and count the number of NON COMPLETIONS and SENT statuses which occurred between that time.
Below is an image of the sample data as well as the sql for the table. Hope somebody can provide a little help. (using SQL server 2005 compatibility)
CREATE TABLE #temp
(
Identifier varchar(20)NOT NULL
,CreatedDate DATETIME NOT NULL
,CompletedDate DATETIME NOT NULL
,SN_Type varchar(20) NOT NULL
,SN_Status varchar(20) NOT NULL
)
;
INSERT INTO #temp
VALUES('64074558792','20160729','20160805','Re-Activattion','SENT');
INSERT INTO #temp
VALUES('64074558792','20160810','20160810','Re-Activattion','N-CO');
INSERT INTO #temp
VALUES('64074558792','20160812','20160812','Re-Activattion','N-CO');
INSERT INTO #temp
VALUES('64074558792','20160811','20160811','Re-Activattion','COMP');
INSERT INTO #temp
VALUES('64074558792','20160811','20160813','Re-Activattion','N-CO');
INSERT INTO #temp
VALUES ('61030203647','20160427','20160427','Re-Activattion', 'COMP');
INSERT INTO #temp
VALUES('61030203647','20160425','20160425','Re-Activattion', 'N-CO');
INSERT INTO #temp
VALUES('61030203647','20160422','20160422','Re-Activattion', 'N-CO');
INSERT INTO #temp
VALUES('61030203647','20170210','20170210','Re-Activattion', 'COMP');
INSERT INTO #temp
VALUES('61030203688','20170409','20170210','Re-Activattion', 'SENT');
INSERT INTO #temp
VALUES('61030203699','20170409','20170210','De-Activattion', 'COMP');
I am not sure whether this covers your requirement or not,
select identifier,count(1) as cnt,sum(case when sn_status = 'N-CO' then 1 else 0 end) as non_com_cnt ,sum(case when sn_status = 'SENT' then 1 else 0 end) as
sent_cnt, datediff(dd,min(case when sn_status = 'SENT' then createddate end),max(case when sn_status = 'COMP' then completeddate end)) as diff,min(case when sn_status = 'SENT' then createddate end) as start_date,max(case when sn_status = 'COMP' then completeddate end) from #temp where sn_type = 'Re-Activattion' group by identifier;

Conditional RowNumber

I am trying to put conditional numbering depending on a result from RowNum column.
When the RowNum is 1 I would like to have new column with brand new increment by 1.
In the picture in column RoomNum 5 should be replaced by 2, 9 by 3m 13 by 4, etc. What am I doing wrong in this query?
SELECT CASE
WHEN rownum < 2
THEN
Row_number() OVER (
PARTITION BY Scheme ORDER BY Scheme ASC
)
ELSE NULL
END AS RoomNum,
CASE
WHEN rownum > 1
THEN NULL
ELSE scheme
END AS Scheme
,RowNum
You need to partition by whether or not RoomNm is NULL. The resulting value would also have a CASE:
select (case when roomnum is not null
then row_number() over (partition by scheme, (case when roomnum is not null then 1 else 0 end)
order by roomnum
)
end) as RoomNum
--I think you can work around this way
--I have little different scenario but hope logic help
declare #ts table
(WK_DAYS int
,DAY_NAME VARCHAR(12)
,WORKTYPE varchar(50)
,WK_HOURS int
,workday int)
insert into #ts (WK_DAYS,DAY_NAME,WORKTYPE,WK_HOURS) values (1,'MON','SICK',8)
insert into #ts (WK_DAYS,DAY_NAME,WORKTYPE,WK_HOURS) values (2,'TUE','LABOR',8)
insert into #ts (WK_DAYS,DAY_NAME,WORKTYPE,WK_HOURS) values (3,'WED','LABOR',8)
insert into #ts (WK_DAYS,DAY_NAME,WORKTYPE,WK_HOURS) values (4,'THU','VACATION',8)
insert into #ts (WK_DAYS,DAY_NAME,WORKTYPE,WK_HOURS) values (5,'FRI','LABOR',8)
insert into #ts (WK_DAYS,DAY_NAME,WORKTYPE,WK_HOURS) values (6,'SAT','LABOR',8)
insert into #ts (WK_DAYS,DAY_NAME,WORKTYPE,WK_HOURS) values (7,'SUN','LABOR',8)
SELECT * FROM #TS
SELECT
X.*
,Y.WORKING_DAY
FROM
(SELECT * FROM #ts)X
LEFT JOIN
(SELECT *,ROW_NUMBER()OVER (ORDER BY WK_DAYS) AS WORKING_DAY FROM #ts WHERE WORKTYPE NOT IN ('SICK','VACATION','SATURDAY','SUNDAY'))Y
ON X.WK_DAYS = Y.WK_DAYS

Excluding blank rows in CTE query

I am new to using CTE queries in SQL Server. I've built this query with help from the web in an effort to start building my "change log" to highlight changes made in my database. Please see example linked below. I'd like to exclude rows where there are no changes. Can you assist in how to accomplish this?
Row #3 with Nov 7 changedate has blank values. I would like for this row to not display. I also don't want to have to do something like WHERE row1 <> '' AND row2 <> '' AND row3 <> '', etc, because my final query will contain much much more rows. Is this possible?
http://sqlfiddle.com/#!6/134bd/4/0
Here is an option that you can use.
Below uses COALESCE function.
Using the same data and just modified your code from sqlfiddle.
The CASE statement to return NULL when match and cast data types to varchar, then use COALESCE in the where
Below modified script to include nTEXT column. You can use DATALENGTH with COALESCE in the WHERE clause.
Modified:
CREATE TABLE tblEmp
([memid] int, [empid] int, [name] varchar(50),[salary] int, [room] varchar(50), changedate datetime, ntxt ntext);
INSERT INTO tblEmp
([memid], [empid], [name], [salary], [room], [changedate], [ntxt])
VALUES
(41, 1, 'peter', 1000, 'Regency', '11/4/2012', ''),
(43, 1, 'peterz', 2000, 'Regency','11/5/2013', 'nn') ,
(44, 1, 'peterz', 2000, 'Regency','11/7/2013', '') ,
(45, 4, 'sally', 2001, 'Sheratio','11/2/2013', '') ,
(46, 4, 'sally', 2000, 'Sheraton','11/6/2013', ''),
(47, 1, 'peter', 3000, 'Regency','12/4/2013', '') ,
(48, 4, 'sallye', 2000,'Sheraton 1', '11/9/2013', '') ,
(49, 4, 'sally', 3000, 'Sheraton','11/6/2013', 'kljslkdjflkajslkjasdlkjalskjdlakjsdlkjasldjfk')
;
WITH cte AS
(
SELECT
empid,
name,
salary, room,
changedate,
ntxt,
rn=ROW_NUMBER()OVER(PARTITION BY empid ORDER BY changedate)
FROM tblemp
)
SELECT *
FROM
(
SELECT c1.empid, oldname=CASE WHEN c1.Name=c2.Name THEN NULL ELSE C1.Name END,
newname=CASE WHEN c1.Name=c2.Name THEN NULL ELSE C2.Name END,
oldsalary=CASE WHEN c1.salary=c2.salary THEN NULL ELSE C1.salary END,
newsalary=CASE WHEN c1.salary=c2.salary THEN NULL ELSE C2.salary END,
oldroom=CASE WHEN c1.Room=c2.Room THEN NULL ELSE C1.Room END,
newroom=CASE WHEN c1.room=c2.room THEN NULL ELSE C2.room END,
c2.changedate
, c2.ntxt
FROM cte c1 INNER JOIN cte c2
ON c1.empid=c2.empid AND c2.RN=c1.RN+1
) x
WHERE NOT (COALESCE(oldname, newname, CAST(oldsalary AS VARCHAR), CAST(newsalary AS VARCHAR), CAST(oldroom AS VARCHAR), CAST(newroom AS VARCHAR)) is null
AND DATALENGTH(ntxt) = 0)
ORDER BY ChangeDate DESC
A slightly different approach with SQL Server 2012 would be to use LAG in the common table expression to be able to detect row by row changes. The CTE basically pulls out each row along with the relevant data from the previous row, and does a straight forward compare in the outer query to generate the result.
WITH cte AS (
SELECT
empid, changeDate,
LAG(name) OVER (PARTITION BY empid ORDER BY changeDate) oldname, name,
LAG(salary) OVER (PARTITION BY empid ORDER BY changeDate) oldsalary, salary,
LAG(room) OVER (PARTITION BY empid ORDER BY changeDate) oldroom, room
FROM tblEmp
)
SELECT empid,
CASE WHEN name<>oldname THEN oldname ELSE '' END oldname,
CASE WHEN name<>oldname THEN name ELSE '' END newname,
CASE WHEN salary<>oldsalary THEN oldsalary ELSE '' END oldsalary,
CASE WHEN salary<>oldsalary THEN salary ELSE '' END newsalary,
CASE WHEN room<>oldroom THEN oldroom ELSE '' END oldroom,
CASE WHEN room<>oldroom THEN room ELSE '' END newroom,
changeDate
FROM cte
WHERE oldname<>name OR oldsalary<>salary OR oldroom<>room
ORDER BY empid, changeDate;
An SQLfiddle to test with.

sql query serial number

I have written a stored procedure in SQL Server 2000. I want a serial number for output table.
So when I run this stored proc I get this error:
An explicit value for the identity column in table
'#tmpSearchResults1' can only be specified when a column list is used
and IDENTITY_INSERT is ON.
I have tried with set IDENTITY_INSERT #tmpSearchResults1 on
Create Procedure dbo.usp_mobile_All_KeyWord(#searchkey varchar(30))
AS
CREATE TABLE #tmpSearchResults
(
property_id varchar(255),
property_number varchar(255),
auction_date_reason varchar(255)
)
INSERT INTO #tmpSearchResults
SELECT
p.property_id, p.property_number, p.auction_date_reason
FROM
Pr p
INNER JOIN
Au a ON p.auction_id = a.auction_id
INNER JOIN
PrAdd pa ON p.property_id = pa.property_id
INNER JOIN state AS s ON s.state_id=pa.state
where
(
(p.archive = 'N'
AND
a.show_on_site = 'Y'
AND
(
(
((p.auction_date >= CONVERT(datetime, CONVERT(varchar, GETDATE(), 103), 103) and (p.auction_date_reason is null or p.auction_date_reason = ''))
or
(p.auction_date <= CONVERT(datetime, CONVERT(varchar, GETDATE(), 103), 103) and ( p.auction_date_reason = 'Accepting Offers' )))
and
pa.property_address_type_id = 1 )) )
and
(state_abbreviation=#searchkey or s.state_name like '%'+''+ #searchkey +''+'%' or city like '%'+''+ #searchkey +''+'%' or pa.address1 like '%'+''+ #searchkey +''+'%'
or pa.address2 like '%'+''+ #searchkey +''+'%')
)
)
CREATE TABLE #tmpSearchResults1
(
i1 int identity,
property_id varchar(255),
property_number varchar(255),
auction_date_reason varchar(255)
)
insert into #tmpSearchResults1
select
property_id ,
property_number,
auction_date_reason
from #tmpSearchResults
order by
case when charindex(#searchkey,state) >0 then 1000 else 0 end desc,
case when charindex(#searchkey,statename) >0 then 1000 else 0 end desc,
case when charindex(#searchkey,city) >0 then 1000 else 0 end desc,
case when charindex(#searchkey,address2) >0 then 1000 else 0 end desc,
case when charindex(#searchkey,address1) >0 then 1000 else 0 end desc,
case when charindex(#searchkey,short_description) >0 then 1000 else 0 end desc
select * from #tmpSearchResults1
Plz do help me
The error code is very very very clear.
The relevant portion is ...when a column list is used....
You need to specify your column list in the INSERT statement.
INSERT INTO #tmpSearchResults
(i1,
property_id,
property_number,
auction_date_reason)
SELECT
p.property_id, p.property_number, p.auction_date_reason
FROM...
First, there is a comma too much in the SELECT part of your second statement:
insert into #tmpSearchResults1
select
property_id ,
property_number,
auction_date_reason , <-- THIS ONE!!
from #tmpSearchResults
The last column of a SELECT statement must be without a comma.
So this would be correct:
insert into #tmpSearchResults1
select
property_id ,
property_number,
auction_date_reason
from #tmpSearchResults
Second, did you read this part of the error message?
An explicit value [...] can only be specified when a column list is used
The "column list" part means that you have to specify the columns in the INSERT part:
insert into #tmpSearchResults1
(property_id, property_number, auction_date_reason)
select
property_id ,
property_number,
auction_date_reason
from #tmpSearchResults
You can get away with not specifying the columns when the number of columns in the SELECT statement is the same as in the table in which they should be inserted (and if the data types match).
If one of these conditions is not met, you need to specify the columns because otherwise SQL Server doesn't know which value to insert into which column.