Group multiple result set by count - sql

I have a query which loops over some data and returns a count if true. However because of the loop the count only counts that result, so you just get 1,1,1,1 returned etc.. rather than 4.
WHILE (#I <= #RowCount)
BEGIN
DECLARE #forename VARCHAR(50)
DECLARE #surname VARCHAR(50)
SELECT #DOB = forename FROM #mytemp WHERE row = #I
SELECT #forename = forename FROM #mytemp WHERE row = #I + 1
SELECT #surname = forename FROM #mytemp WHERE row = #I + 2
SELECT COUNT(*) FROM [FPTDB].dbo.clients WHERE forename = #forename AND surname = #surname AND dob = #DOB
SET #I = #I + 3
END
I presume i need to group the result set somehow to count the results, but i'm not sure how.

I suggest skip WHILE and you can do like this (last select is not tested):
DECLARE #mytemp TABLE (forename VARCHAR(100))
INSERT INTO #mytemp SELECT 'tom'
INSERT INTO #mytemp SELECT 'bob'
INSERT INTO #mytemp SELECT 'smith'
INSERT INTO #mytemp SELECT 'mary'
INSERT INTO #mytemp SELECT 'tedy'
INSERT INTO #mytemp SELECT 'carry'
INSERT INTO #mytemp SELECT 'wmary'
INSERT INTO #mytemp SELECT 'wtedy'
INSERT INTO #mytemp SELECT 'wcarry'
--ADD surname, forename and DOB numbering to table (column isType)
;WITH mytemp AS (
SELECT forename, ROW_NUMBER() OVER (ORDER BY forename) as ID
FROM #mytemp
)
SELECT forename,
CASE
WHEN ID % 3 = 0 THEN 3 --surname
WHEN ID % 3 = 2 THEN 2 --forename
ELSE 1 -- DOB
END AS isType
INTO #myTemp2
FROM mytemp
ORDER BY ID
/*result like this
forename ID isType
bob 1 1
carry 2 2
mary 3 3
smith 4 1
tedy 5 2
tom 6 3
wcarry 7 1
wmary 8 2
wtedy 9 3
*/
--Join just created table 3 times
SELECT COUNT(*)
FROM [FPTDB].dbo.clients AS C
INNER JOIN #myTemp2 AS T1 --DOB
ON T1.forename= C.dob
AND T1.isType = 1
INNER JOIN #myTemp2 AS T2 --forename
ON T2.forename = C.forename
AND T2.isType = 2
INNER JOIN #myTemp2 AS T3 --surname
ON T3.forename= C.surname
AND T3.isType = 3

You should add another variable and store the sum of every loop count in it.
After the loop you can output the variable value.
DECLARE #tot INT unsigned
SELECT #tot = 0
WHILE (#I <= #RowCount)
BEGIN
DECLARE #forename VARCHAR(50)
DECLARE #surname VARCHAR(50)
SELECT #DOB = forename FROM #mytemp WHERE row = #I
SELECT #forename = forename FROM #mytemp WHERE row = #I + 1
SELECT #surname = forename FROM #mytemp WHERE row = #I + 2
SELECT #tot = #tot + COUNT(*) FROM [FPTDB].dbo.clients WHERE forename = #forename AND surname = #surname AND dob = #DOB
SET #I = #I + 3
END
SELECT #tot

Related

Concate string into temp table in cursor

I have a temp table structure #temp2 like this
route total driverID
------------------------
10B 300
7B 400
and would like to add the driverID column with a result like 5555, 68989
to do this, I use the cursor to loop another table look like this
driverID routeNo
-------------------
5555 10B
68989 10B
72000 7B
Here is the code
declare #driverID varchar(max)
declare #routeNew varchar(20)
DECLARE brand_cursor CURSOR FOR
select distinct driver_id, route_number from [dbcwl].[dbo].[collection_deduction_summary]
where YEAR(trans_date) = #year
and MONTH(trans_date) = #month
and route_number in (select actual_route from [dbcwl].[dbo].[livedispatchingdata_pmhs_daily_summary] where status = 'OK' and YEAR(trans_date) = #year AND month(trans_date) = #month )
and vehicle_id in (select vehicle_id from [dbcwl].[dbo].[livedispatchingdata_pmhs_daily_summary] where status = 'OK' and YEAR(trans_date) = #year AND month(trans_date) = #month )
group by route_number, driver_id
OPEN brand_cursor
FETCH NEXT FROM brand_cursor
INTO #driverID, #routeNew
WHILE ##FETCH_STATUS = 0
BEGIN
--update #temp2
update #temp2 set driverID += ','+ #driverID where routeNo = #routeNew;
FETCH NEXT FROM brand_cursor
INTO #driverID, #routeNew
END
CLOSE brand_cursor;
DEALLOCATE brand_cursor;
sadly, I got the driverID column is null
and would like to have finalized temp table look like this:
route total driverID
------------------------
10B 300 5555,68989
7B 400 72000
;with cte as -- Step 1: Get all Driver Ids by routeNo
(
SELECT routeNo, driverID =
STUFF((SELECT DISTINCT ', ' + CAST(driverID AS NVARCHAR(100))
FROM #A b
WHERE b.routeNo = a.routeNo
FOR XML PATH('')), 1, 2, '')
FROM #A a
GROUP BY routeNo
)
update b -- Step 2: Update driverID accordingly.
set driverID = cte.driverID
from #B b
inner join cte on b.route = cte.routeNo
Result here
You can string_agg():
update t
set t.driverID = ot.drivers
from #temp2 t join
(select ot.routeNo, string_agg(driverID, ',') as drivers
from othertable ot
group by ot.routeNo
) ot
on t.routeNo = ot.routeNo;

Refresh issue with Stored Procedure in MSSQL

I have one SP for mobile application chat app (used with API) it has 25 filters and 10 tables join and return posts for user, it works good for 2 days but after 2 days it stop working, then i need to refresh it again with alter query or something then it start working for next few days.
If filter stop for any particular user than why others have issue with SP.
USE [DatabaseName]GOSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER PROC [dbo].[uspGetShoutouts] (
#UserId UNIQUEIDENTIFIER,
#anotherUserid UNIQUEIDENTIFIER,
#Interest NVARCHAR(100),
#Gender NVARCHAR(100),
#AgeFrom INT,
#AgeTo INT,
#StartLatitude NUMERIC(20,15),
#StartLongitude NUMERIC(20,15),
#Radius FLOAT,
#Location BIT = NULL,
#IsTraveler BIT,
#IsLocal BIT,
#HomeTownCity VARCHAR(100),
#UserName NVARCHAR(200),
#FirstName NVARCHAR(200),
#LastName NVARCHAR(200),
#CreatedDate DATETIME,
#IsMyShoutout BIT,
#ShoutoutTypeId INT=0,
#PostTypeId INT=0,
#oldMoment BIT,
#SortExpression CHAR(1) = 1,
#CurrentPage INT = 1,
#PageSize INT = 10,
#IsFriend BIT=0,
#IsPrivate BIT,
#GroupId NVARCHAR(200),
#TotalRows INT OUTPUT
)
AS
BEGIN
DECLARE #UserList TABLE(
UserId uniqueidentifier,
FirstName NVARCHAR(100),
LastName NVARCHAR(100),
QuickBloxId NVARCHAR(100),
SocialId NVARCHAR(100),
Gender char(1),
Email NVARCHAR(100),
IsProfileImageSync bit,
IsFriend bit,
IsRequestSent bit,
RequestSender NVARCHAR(100),
IsBlocked bit,
FriendBlocked bit,
Age int,
HomeTownCity NVARCHAR(100),
ImageName NVARCHAR(200),
Distance numeric(20,6),
DistanceTemp numeric(20,6),
LastActiveDateTime datetime,
ShoutoutGuid uniqueidentifier,
ShoutoutId bigint not null,
InterestId int,
InterestName NVARCHAR(100),
ShoutoutImageName NVARCHAR(200),
Description NVARCHAR(max),
CreatedOn DateTime,
IsImageSync bit,
DisplayUpdatedOn NVARCHAR(50),
ShoutoutCity NVARCHAR(500),
ShoutoutCountry NVARCHAR(500),
AdministrativeAreaLevel1 NVARCHAR(500),
PlaceId NVARCHAR(500),
FormattedAaddress NVARCHAR(500),
Url NVARCHAR(500),
TotalLike int,
TotalComment int,
Selflike bit,
ShoutoutTypeId int,
ShoutoutType NVARCHAR(200),
PostTypeId int,
PostTypeName NVARCHAR(200),
oldMoment bit,
UserLatitude numeric(20,6),
UserLongitude numeric(20,6),
ShoutoutLatitude numeric(20,6),
ShoutoutLongitude numeric(20,6),
DistanceShoutoutMiles numeric(20,6)
)
SET NOCOUNT ON;
DECLARE #StartLatitude1 numeric(20,2) = #StartLatitude
DECLARE #StartLongitude1 numeric(20,2) =#StartLongitude;
;with
UserList as (
select
distinct
USRSHTOUT.ShoutoutId,
USRSHTOUT.ShoutoutGuid,
U.UserId,
U.FirstName,
U.LastName,
U.QuickbloxId,
convert(int,round(datediff(hour,dob,getdate())/8766.0,0)) as Age,
U.SocialId,
U.Gender,
U.Email,
isnull(U.IsProfileImageSync,0) IsProfileImageSync,
U.HomeTownCity,
U.ImageName,
isnull(fr.IsFriend,0) as IsFriend,
isnull(fr.IsRequestSent,0) as IsRequestSent,
isnull(fr.RequestSender,cast(cast(0 as binary) as uniqueidentifier)) as RequestSender,
isnull(fr.IsBlocked,0) as IsBlocked,
isnull(fr.FriendBlocked,0) as FriendBlocked,
[dbo].[fnCalcDistanceKM](cast(#StartLatitude1 as float),cast(#StartLongitude1 as float),cast (isnull(USRSHTOUT.Latitude,0) as float) ,cast(isnull(USRSHTOUT.Longitude,0) as float)) as Distance,
(geography::Point(coalesce(USRSHTOUT.Latitude,0), coalesce(USRSHTOUT.Longitude,0), 4326).STDistance(geography::Point(#StartLatitude1, #StartLongitude1, 4326))/1000) as DistanceTemp,
ULAL.UpdatedOn as LastActiveDateTime,
0 as InterestId,
'' as InterestName,
isnull(USRSHTOUT.ImageName,'') 'ShoutoutImageName',
isnull(USRSHTOUT.Description,'') Description,USRSHTOUT.CreatedOn,IsImageSync,
isnull(format(UGL.UpdatedOn,'dd-MMM, yyyy HH:mm tt'),'') 'DisplayUpdatedOn',
isnull(ADC.locality,'')[ShoutoutCity],
isnull(ADC.country,'')[ShoutoutCountry],
isnull(ADC.administrative_area_level_1,'') [AdministrativeAreaLevel1],
isnull(ADC.place_id,'') [PlaceId],
isnull(ADC.formatted_address,'') FormattedAaddress,
isnull(ADC.url,'') Url,
isnull(lt.TotalLike, 0) as TotalLike,
isnull(ct.TotalComment, 0) as TotalComment,
isnull(lt.SelfLike, 0) as SelfLike,
SHT.ShoutoutTypeId,
isnull(SHT.Name,'') ShoutoutType,
UPT.PostTypeId,
isnull(UPT.Name,'') PostTypeName,
USRSHTOUT.oldMoment,
UGL.Latitude 'UserLatitude',
UGL.Longitude 'UserLongitude',
USRSHTOUT.Latitude 'ShoutoutLatitude',
USRSHTOUT.Longitude 'ShoutoutLongitude',
DistanceShoutoutMiles
from
Users U
inner join UserShoutouts USRSHTOUT on U.UserId=USRSHTOUT.UserId
left join UserLastActivityLog ULAL on ULAL.UserId=U.UserId
left join UserGeoLocation UGL on UGL.UserId=U.UserId
left join AddressShoutoutMapping ASMP on ASMP.ShoutoutId=USRSHTOUT.ShoutoutId
left join AddressComponents ADC on ADC.AddressComponentId=ASMP.AddressComponentId
left join [ShoutoutType] SHT on SHT.ShoutoutTypeId=isnull(USRSHTOUT.ShoutoutTypeId,0)
LEFT JOIN [UserPostType] UPT ON UPT.PostTypeId = ISNULL(USRSHTOUT.PostTypeId,0)
cross apply (select cos(radians(#StartLatitude1)) * cos(radians(USRSHTOUT.Latitude)) * cos(radians(USRSHTOUT.Longitude) - radians(#StartLongitude1)) + sin(radians(#StartLatitude1)) * sin(radians(USRSHTOUT.Latitude))) T(ACosInput)
cross apply (select ((3959 * acos(case when abs(ACosInput) > 1 then sign(ACosInput)*1 else ACosInput end)))) T2(DistanceShoutoutMiles)
left join (
select ItemId,
count(1) TotalLike,
cast(sum(case when UserId = #anotherUserid then 1 else 0 end) as bit) as SelfLike
from dbo.LikeDetails
where Liked=1 and LikeSourceId=1
group by ItemId) as lt on USRSHTOUT.ShoutoutId = lt.ItemId
left join (
select ParentId,
count(1) as TotalComment
from Comments
where CommentSourceId=1 and Comments.IsDeleted=0
group by ParentId) as ct on USRSHTOUT.ShoutoutId = ct.ParentId
left join dbo.tvf_GetFriendsByUserId (#UserId) fr on u.UserId = fr.ThisFriendId
left join UserShoutoutsPrivate USP on USP.ShoutoutId = USRSHTOUT.ShoutoutId
left join UserInterest UI on UI.InterestId = USP.GroupId
left join Interest INTRST on INTRST.Id = UI.InterestId
where
USRSHTOUT.IsDeleted=0
and (((#oldMoment = 0) and USRSHTOUT.oldMoment = #oldMoment)
or ((#oldMoment = 1) and USRSHTOUT.oldMoment = 1 or USRSHTOUT.oldMoment = 0) )
and U.IsEmailVerified=1 and isnull(U.IsDeactivated,0)=0
and (#ShoutoutTypeId=0 or USRSHTOUT.ShoutoutTypeId=#ShoutoutTypeId)
and (#IsMyShoutout=0 or (#IsMyShoutout=1 and USRSHTOUT.UserId = #UserId))
and ((#UserName is not null and #UserName='all'
OR ((U.FirstName + ' ' + U.LastName) = #UserName)OR (U.FirstName like LTRIM(RTRIM(#UserName))+'%') OR (U.LastName like LTRIM(RTRIM(#UserName))+'%'))
OR ( #FirstName is not null AND #LastName is null and
((U.FirstName = #FirstName ) OR (U.FirstName like LTRIM(RTRIM(#FirstName))+'%')))
OR ( #LastName is not null AND #FirstName is null and
((U.LastName = #LastName ) OR (U.LastName like LTRIM(RTRIM(#LastName))+'%')))
OR ((( #FirstName is not null AND #LastName is not null AND
((U.FirstName + ' ' + U.LastName) = #FirstName + ' ' + #LastName) OR (U.FirstName like LTRIM(RTRIM(#FirstName))+'%')) and (U.LastName like LTRIM(RTRIM(#LastName))+'%'))))
and((#Interest <>'' AND #IsPrivate = 1 AND (exists (select * from dbo.UserInterest where (UserId = U.UserId and InterestId in (select * from dbo.Split(#Interest,','))))
or #Interest ='')
or(#IsPrivate = 1
and (UI.Interestid in (select items from dbo.Split(#GroupId,',')) and INTRST.IsPrivate = 1 and INTRST.IsDelete = 0 and USRSHTOUT.IsDeleted=0 and
USP.ShoutoutId = USRSHTOUT.ShoutoutId and UI.IsActive = 1 and USP.GroupId in (select items from dbo.Split(#GroupId,','))))
)
OR(#Interest <>'' AND #IsPrivate = 0 AND (exists (select * from dbo.UserInterest where (UserId = U.UserId and InterestId in (select * from dbo.Split(#Interest,','))))
or #Interest ='')
or(#IsPrivate = 1
and (UI.Interestid in (select items from dbo.Split(#GroupId,',')) and INTRST.IsPrivate = 1 and INTRST.IsDelete = 0 and USRSHTOUT.IsDeleted=0 and
USP.ShoutoutId = USRSHTOUT.ShoutoutId and UI.IsActive = 1 and USP.GroupId in (select items from dbo.Split(#GroupId,','))))
)
OR(#Interest ='' AND #IsPrivate = 0 AND (exists (select * from dbo.UserInterest where (UserId = U.UserId and InterestId in (select * from dbo.Split(#Interest,','))))
or #Interest =''))
)
and (#PostTypeId=0 or USRSHTOUT.PostTypeId=#PostTypeId)
)
insert into #UserList
select
UserId,
FirstName,
LastName,
QuickBloxId,
SocialId,
Gender,
Email,
IsProfileImageSync,
IsFriend,
IsRequestSent,
RequestSender,
IsBlocked,
FriendBlocked,
Age,
HomeTownCity,
ImageName,
Distance,
DistanceTemp,
LastActiveDateTime,
ShoutoutGuid,
ShoutoutId,
InterestId,
InterestName,
ShoutoutImageName,
Description,
CreatedOn,
IsImageSync,
DisplayUpdatedOn,
ShoutoutCity,
ShoutoutCountry,
AdministrativeAreaLevel1,
PlaceId,
FormattedAaddress,
Url,
u.TotalLike,
u.TotalComment,
u.Selflike,
ShoutoutTypeId,
ShoutoutType,
PostTypeId,
PostTypeName,
oldMoment,
UserLatitude,
UserLongitude,
ShoutoutLatitude,
ShoutoutLongitude,
DistanceShoutoutMiles
from UserList u
where
(#Gender ='' or ((Gender in(select * from dbo.Split(#Gender,','))) or (#Gender like '%3%' and Gender=0)))
and(
((#AgeFrom = 18) AND ((#AgeTo= 65 and Age >= 15 )
or (Age >= 15 and Age <= #AgeTo)))
OR
((#AgeTo= 65 and Age >= #AgeFrom )
or (Age >= #AgeFrom and Age <= #AgeTo))
)
and IsBlocked <> 1
and FriendBlocked <> 1
and (#Location=0 or ((DistanceShoutoutMiles<= #Radius) or (#IsLocal=1 and HomeTownCity=#HomeTownCity)))
and (#IsFriend=0 or (#IsFriend=1 and IsFriend=1))
and (#Location=0 or (
((#IsTraveler=1 and #IsLocal=1) or (#IsTraveler=0 and #IsLocal=0)) or
((#IsTraveler=1 and #IsLocal=0 and lower(HomeTownCity) != lower(#HomeTownCity))
or (#IsTraveler=0 and #IsLocal=1 and lower(HomeTownCity) = lower(#HomeTownCity)))))OPTION(RECOMPILE)
set #TotalRows = ##rowcount
IF(#CurrentPage=0)
begin
select * from #UserList order by Distance asc OPTION(OPTIMIZE FOR UNKNOWN)
end
ELSE
BEGIN
declare #OffSetSize as bigint
set #OffSetSize = ((#CurrentPage * #PageSize) - #PageSize)
IF (#SortExpression = '1')
BEGIN
SELECT *
FROM #UserList
WHERE CreatedOn<#CreatedDate
ORDER BY CreatedOn DESC
OFFSET #OffSetSize ROWS
FETCH NEXT #PageSize ROWS ONLY
OPTION(OPTIMIZE FOR UNKNOWN)
END
ELSE IF (#SortExpression = '2')
BEGIN
SELECT *
FROM #UserList
WHERE CreatedOn>#CreatedDate
ORDER BY CreatedOn DESC
OFFSET #OffSetSize ROWS
FETCH NEXT #PageSize ROWS ONLY
OPTION(OPTIMIZE FOR UNKNOWN)
END
ELSE IF (#SortExpression = '3')
BEGIN
SELECT *
FROM #UserList
ORDER BY Distance ASC, CreatedOn DESC
OFFSET #OffSetSize ROWS
FETCH NEXT #PageSize ROWS ONLY
OPTION(OPTIMIZE FOR UNKNOWN)
END
ELSE IF (#SortExpression = '4')
BEGIN
SELECT *
FROM #UserList
ORDER BY Distance ASC
OFFSET #OffSetSize ROWS
FETCH NEXT #PageSize ROWS ONLY
OPTION(OPTIMIZE FOR UNKNOWN)
END
ELSE
BEGIN
SELECT *
FROM #UserList
ORDER BY CreatedOn DESC
OFFSET #OffSetSize ROWS
FETCH NEXT #PageSize ROWS ONLY
OPTION(OPTIMIZE FOR UNKNOWN)
END
END
ENDGO

How do I modify this T-SQL query so that its ouput can be joined with a table in my database?

I am using SQl Server 2014. I have the following T-SQL query (with its corresponding output given below):
USE mydatabase
declare #t table (StayID int)
insert into #t select distinct StayID from DateOfBirth
while ((select count(1) from #t) > 0)
begin
declare #Id int = (select top 1 StayID from #t)
declare #age_tab table (StayID int, Age int, Year1 date)
declare #cage1 smallint = 2, #cage2 smallint = 5
declare #i_a int = (select AdultCount from DateOfBirth where StayID = #Id)
declare #i_c1 int = (select [0-3] from DateOfBirth where StayID = #Id)
declare #i_c2 int = (select [4-6] from DateOfBirth where StayID = #Id)
declare #age int = (select Age from DateOfBirth where StayID = #Id)
declare #Year1 date = (select cast(datepart(year,ArrivalDate) as varchar) from DateOfBirth where StayID = #Id)
while (#i_a>1)
begin
insert into #age_tab select #Id, (#age + 2), #Year1
set #age-=2
set #i_a-=1
end
while (#i_c1>0)
begin
insert into #age_tab select #Id, #cage1, #Year1
set #i_c1-=1
end
while (#i_c2>0)
begin
insert into #age_tab select #Id, #cage2, #Year1
set #i_c2-=1
end
insert into #age_tab select StayID, Age, cast(datepart(year,ArrivalDate) as varchar) from DateOfBirth where StayID = #Id
delete #t where StayID = #Id
end
select * from #age_tab
order by StayID, Age desc
The output of the above query is as follows:
StayID Age Year1
101 54 2016-01-01
101 52 2016-01-01
102 42 2016-01-01
102 40 2016-01-01
102 14 2016-01-01
...
I want to join the output of this query with values from another table in my database. Given the above query uses temporary tables to perform its operation, I am unable to wrap it into a CTE.
The additional information I want to bring to my output is stored in, say, table "t2".
Let's say the output from the query above is temporarily stored in a table called "t1"
So, I want to do something like this:
Select a.*
, b.Cty
from t1 a
LEFT JOIN t2 b on b.StayID = a.StayID
How can I do this?

Is it possible to group unlike items and count them together?

Given the following table:
Chain Name
123 Company 1
124 Other Company 1
123 Whatever Company
125 This One
126 That One
125 Another One
127 Last One
I get the following results when I do a Count on the Chain column:
123 2
124 1
125 2
126 1
127 1
Is it possible to group Chain 123 and 124 so they're counted together? Also group 125 and 126? The modified results would look like this:
123/124 3
125/126 3
127 1
My SQL looks like this:
SELECT Table1.Chain, Count(*) as [Count]
FROM Table1 LEFT JOIN Table2 on Table1.Chain = Table2.Chain
WHERE (((Table1.Chain) IN (Table2.Chain)))
GROUP BY Table1.Chain
ORDER BY Table1.Chain;
Thank you!
Depending upon your needs, this might be a bit of a hack, but I would probably add a table to store the Chain and ChainGroup that you are seeking. Something like this:
Chain ChainGroup
123 123/124
124 123/124
125 125/126
126 125/126
127 127/128
Then, in the query, I would join to this table and instead of grouping by Chain I would group by ChainGroup.
I would prefer this over something like a nested IIF statement as those get pretty difficult to debug, and odds are you'll have additional groupings in the future which would be trivial to add to the table and have the new grouping automatically appear in the query.
yes, you can:
SELECT min(Table1.Chain) & '/' & max(Table1.Chain) as chain, Count(*) as [Count]
FROM Table1 LEFT JOIN Table2 on Table1.Chain = Table2.Chain
WHERE (((Table1.Chain) IN (Table2.Chain)))
GROUP BY int((Table1.Chain-1)/2)
ORDER BY min(Table1.Chain);
You can use a nested Iif statement. Hopefully I've got all my parentheses right below! :-)
SELECT Iif(Table1.Chain="123", "123/124",
Iif(Table1.Chain="124", "123/124",
Iif(Table1.Chain="125", "125/126",
Iif(Table1.Chain="126", "125/126", Table1.Chain)))) as [Chain]
, Count(*) as [Count]
FROM Table1 LEFT JOIN Table2 on Table1.Chain = Table2.Chain
WHERE (((Table1.Chain) IN (Table2.Chain)))
GROUP BY Iif(Table1.Chain="123", "123/124",
Iif(Table1.Chain="124", "123/124",
Iif(Table1.Chain="125", "125/126",
Iif(Table1.Chain="126", "125/126", Table1.Chain))))
ORDER BY Table1.Chain;
You could also move the case statement into a subquery in your from clause or a common table expression if you don't want to write it twice in your query.
consider something like:
SELECT
chain_group, COUNT(*) FROM (
SELECT
Table1.Chain,
switch(Table1.Chain IN("123","124"), "123/124",
Table1.Chain IN("125","126"),"125/126",
Table1.Chain) AS chain_group
FROM
Table1 INNER JOIN
Table2 ON
Table1.Chain = Table2.Chain) t
GROUP BY chain_group
ORDER BY chain_group
You can see the below example
----- Make main Table
CREATE TABLE #test
( id int , Name varchar(100))
INSERT #test(id,Name)
values (123,'Company 1'),
(124,'Other Company 1'),
(123, 'Whatever Company'),
(125, 'This One'),
(126 , 'That One'),
(125, 'Another One'),
(127, 'Last One')
CREATE TABLE #temp
(rowID INT IDENTITY(1,1) , ID INT ,cnt INT )
CREATE TABLE #tempResult
(ID VARCHAR(20) ,cnt INT )
INSERT INTO #temp(ID,cnt)
SELECT ID ,COUNT(1) cnt FROM #test GROUP BY ID
DECLARE #rowCnt INT , #TotalCnt INT , #even INT , #odd INT ,
#idNum VARCHAR(20) , #valueCnt INT , #inStart INT = 1
SET #rowCnt = 1
SET #even = 1
SET #odd = 2
SELECT #TotalCnt = COUNT(1) FROM #temp
WHILE #rowCnt <= #TotalCnt
BEGIN
SET #inStart = 1
SET #odd = #rowCnt
SET #even = #rowCnt + 1
SET #idNum = ''
SET #valueCnt = 0
WHILE #inStart <= 2
BEGIN
IF #inStart = 1
Begin
SELECT #idNum = Convert(VARCHAR(5),ID) , #valueCnt = cnt
FROM #temp WHERE rowID = #odd
End
ELSE
BEGIN
SELECT #idNum = #idNum + '/' + Convert(VARCHAR(5),ID) , #valueCnt = #valueCnt + cnt
FROM #temp WHERE rowID = #even
END
SET #inStart = #inStart + 1
END
INSERT INTO #tempResult (ID, Cnt)
VALUES (#idNum,#valueCnt)
SET #rowCnt = #rowCnt + 2
END
SELECT *
FROM #tempResult

SQL query to find Missing sequence numbers

I have a column named sequence. The data in this column looks like 1, 2, 3, 4, 5, 7, 9, 10, 15.
I need to find the missing sequence numbers from the table. What SQL query will find the missing sequence numbers from my table? I am expecting results like
Missing numbers
---------------
6
8
11
12
13
14
I am using only one table. I tried the query below, but am not getting the results I want.
select de.sequence + 1 as sequence from dataentry as de
left outer join dataentry as de1 on de.sequence + 1 = de1.sequence
where de1.sequence is null order by sequence asc;
How about something like:
select (select isnull(max(val)+1,1) from mydata where val < md.val) as [from],
md.val - 1 as [to]
from mydata md
where md.val != 1 and not exists (
select 1 from mydata md2 where md2.val = md.val - 1)
giving summarised results:
from to
----------- -----------
6 6
8 8
11 14
I know this is a very old post but I wanted to add this solution that I found HERE so that I can find it easier:
WITH Missing (missnum, maxid)
AS
(
SELECT 1 AS missnum, (select max(id) from #TT)
UNION ALL
SELECT missnum + 1, maxid FROM Missing
WHERE missnum < maxid
)
SELECT missnum
FROM Missing
LEFT OUTER JOIN #TT tt on tt.id = Missing.missnum
WHERE tt.id is NULL
OPTION (MAXRECURSION 0);
Try with this:
declare #min int
declare #max int
select #min = min(seq_field), #max = max(seq_field) from [Table]
create table #tmp (Field_No int)
while #min <= #max
begin
if not exists (select * from [Table] where seq_field = #min)
insert into #tmp (Field_No) values (#min)
set #min = #min + 1
end
select * from #tmp
drop table #tmp
The best solutions are those that use a temporary table with the sequence. Assuming you build such a table, LEFT JOIN with NULL check should do the job:
SELECT #sequence.value
FROM #sequence
LEFT JOIN MyTable ON #sequence.value = MyTable.value
WHERE MyTable.value IS NULL
But if you have to repeat this operation often (and more then for 1 sequence in the database), I would create a "static-data" table and have a script to populate it to the MAX(value) of all the tables you need.
SELECT CASE WHEN MAX(column_name) = COUNT(*)
THEN CAST(NULL AS INTEGER)
-- THEN MAX(column_name) + 1 as other option
WHEN MIN(column_name) > 1
THEN 1
WHEN MAX(column_name) <> COUNT(*)
THEN (SELECT MIN(column_name)+1
FROM table_name
WHERE (column_name+ 1)
NOT IN (SELECT column_name FROM table_name))
ELSE NULL END
FROM table_name;
Here is a script to create a stored procedure that returns missing sequential numbers for a given date range.
CREATE PROCEDURE dbo.ddc_RolledBackOrders
-- Add the parameters for the stored procedure here
#StartDate DATETIME ,
#EndDate DATETIME
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Min BIGINT
DECLARE #Max BIGINT
DECLARE #i BIGINT
IF OBJECT_ID('tempdb..#TempTable') IS NOT NULL
BEGIN
DROP TABLE #TempTable
END
CREATE TABLE #TempTable
(
TempOrderNumber BIGINT
)
SELECT #Min = ( SELECT MIN(ordernumber)
FROM dbo.Orders WITH ( NOLOCK )
WHERE OrderDate BETWEEN #StartDate AND #EndDate)
SELECT #Max = ( SELECT MAX(ordernumber)
FROM dbo.Orders WITH ( NOLOCK )
WHERE OrderDate BETWEEN #StartDate AND #EndDate)
SELECT #i = #Min
WHILE #i <= #Max
BEGIN
INSERT INTO #TempTable
SELECT #i
SELECT #i = #i + 1
END
SELECT TempOrderNumber
FROM #TempTable
LEFT JOIN dbo.orders o WITH ( NOLOCK ) ON tempordernumber = o.OrderNumber
WHERE o.OrderNumber IS NULL
END
GO
Aren't all given solutions way too complex?
wouldn't this be much simpler:
SELECT *
FROM (SELECT row_number() over(order by number) as N from master..spt_values) t
where N not in (select 1 as sequence union
select 2 union
select 3 union
select 4 union
select 5 union
select 7 union
select 10 union
select 15
)
This is my interpretation of this issue, placing the contents in a Table variable that I can easily access in the remainder of my script.
DECLARE #IDS TABLE (row int, ID int)
INSERT INTO #IDS
select ROW_NUMBER() OVER (ORDER BY x.[Referred_ID]), x.[Referred_ID] FROM
(SELECT b.[Referred_ID] + 1 [Referred_ID]
FROM [catalog].[dbo].[Referrals] b) as x
LEFT JOIN [catalog].[dbo].[Referrals] a ON x.[Referred_ID] = a.[Referred_ID]
WHERE a.[Referred_ID] IS NULL
select * from #IDS
Just for fun, I decided to post my solution.
I had an identity column in my table and I wanted to find missing invoice numbers.
I reviewed all the examples I could find but they were not elegant enough.
CREATE VIEW EENSkippedInvoicveNo
AS
SELECT CASE WHEN MSCNT = 1 THEN CAST(MSFIRST AS VARCHAR (8)) ELSE
CAST(MSFIRST AS VARCHAR (8)) + ' - ' + CAST(MSlAST AS VARCHAR (8)) END AS MISSING,
MSCNT, INV_DT FROM (
select invNo+1 as Msfirst, inv_no -1 as Mslast, inv_no - invno -1 as msCnt, dbo.fmtdt(Inv_dt) AS INV_dT
from (select inv_no as invNo, a4glidentity + 1 as a4glid
from oehdrhst_sql where inv_dt > 20140401) as s
inner Join oehdrhst_sql as h
on a4glid = a4glidentity
where inv_no - invno <> 1
) AS SS
DECLARE #MaxID INT = (SELECT MAX(timerecordid) FROM dbo.TimeRecord)
SELECT SeqID AS MissingSeqID
FROM (SELECT ROW_NUMBER() OVER (ORDER BY column_id) SeqID from sys.columns) LkUp
LEFT JOIN dbo.TimeRecord t ON t.timeRecordId = LkUp.SeqID
WHERE t.timeRecordId is null and SeqID < #MaxID
I found this answer here:
http://sql-developers.blogspot.com/2012/10/how-to-find-missing-identitysequence.html
I was looking for a solution and found many answers. This is the one I used and it worked very well. I hope this helps anyone looking for a similar answer.
-- This will return better Results
-- ----------------------------------
;With CTERange
As (
select (select isnull(max(ArchiveID)+1,1) from tblArchives where ArchiveID < md.ArchiveID) as [from],
md.ArchiveID - 1 as [to]
from tblArchives md
where md.ArchiveID != 1 and not exists (
select 1 from tblArchives md2 where md2.ArchiveID = md.ArchiveID - 1)
) SELECT [from], [to], ([to]-[from])+1 [total missing]
From CTERange
ORDER BY ([to]-[from])+1 DESC;
from to total missing
------- ------- --------------
6 6 1
8 8 1
11 14 4
DECLARE #TempSujith TABLE
(MissingId int)
Declare #Id Int
DECLARE #mycur CURSOR
SET #mycur = CURSOR FOR Select Id From tbl_Table
OPEN #mycur
FETCH NEXT FROM #mycur INTO #Id
Declare #index int
Set #index = 1
WHILE ##FETCH_STATUS = 0
BEGIN
if (#index < #Id)
begin
while #index < #Id
begin
insert into #TempSujith values (#index)
set #index = #index + 1
end
end
set #index = #index + 1
FETCH NEXT FROM #mycur INTO #Id
END
Select Id from tbl_Table
select MissingId from #TempSujith
Create a useful Tally table:
-- can go up to 4 million or 2^22
select top 100000 identity(int, 1, 1) Id
into Tally
from master..spt_values
cross join master..spt_values
Index it, or make that single column as PK.
Then use EXCEPT to get your missing number.
select Id from Tally where Id <= (select max(Id) from TestTable)
except
select Id from TestTable
You could also solve using something like a CTE to generate the full sequence:
create table #tmp(sequence int)
insert into #tmp(sequence) values (1)
insert into #tmp(sequence) values (2)
insert into #tmp(sequence) values (3)
insert into #tmp(sequence) values (5)
insert into #tmp(sequence) values (6)
insert into #tmp(sequence) values (8)
insert into #tmp(sequence) values (10)
insert into #tmp(sequence) values (11)
insert into #tmp(sequence) values (14)
DECLARE #max INT
SELECT #max = max(sequence) from #tmp;
with full_sequence
(
Sequence
)
as
(
SELECT 1 Sequence
UNION ALL
SELECT Sequence + 1
FROM full_sequence
WHERE Sequence < #max
)
SELECT
full_sequence.sequence
FROM
full_sequence
LEFT JOIN
#tmp
ON
full_sequence.sequence = #tmp.sequence
WHERE
#tmp.sequence IS NULL
Hmmmm - the formatting is not working on here for some reason? Can anyone see the problem?
i had made a proc so you can send the table name and the key and the result is a list of missing numbers from the given table
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
create PROCEDURE [dbo].[action_FindMissing_Autoincremnt]
(
#tblname as nvarchar(50),
#tblKey as nvarchar(50)
)
AS
BEGIN
SET NOCOUNT ON;
declare #qry nvarchar(4000)
set #qry = 'declare #min int '
set #qry = #qry + 'declare #max int '
set #qry = #qry +'select #min = min(' + #tblKey + ')'
set #qry = #qry + ', #max = max('+ #tblKey +') '
set #qry = #qry + ' from '+ #tblname
set #qry = #qry + ' create table #tmp (Field_No int)
while #min <= #max
begin
if not exists (select * from '+ #tblname +' where '+ #tblKey +' = #min)
insert into #tmp (Field_No) values (#min)
set #min = #min + 1
end
select * from #tmp order by Field_No
drop table #tmp '
exec sp_executesql #qry
END
GO
SELECT TOP 1 (Id + 1)
FROM CustomerNumberGenerator
WHERE (Id + 1) NOT IN ( SELECT Id FROM CustomerNumberGenerator )
Working on a customer number generator for my company. Not the most efficient but definitely most readable
The table has one Id column.
The table allows for Ids to be inserted at manually by a user off sequence.
The solution solves the case where the user decided to pick a high number