SQL query to know skipped number - sql

Hi im new to SQL query i only know simple query.
My question is it possible to SELECT skipped check number EX2001,EX2002,EX2004
select result will show EX2003.
thanks in advance, sorry for my english.
you can answer algorithm only, ill try to implement it to SQL.
example:
SELECT * FROM SETTLEMENT WHERE checkno not in (between ex2001 and ex2900)
is it possible like this? im using MS SQL 2008.

create table sequence(st varchar(50))
insert into sequence values('EX2001');
insert into sequence values('EX2002');
insert into sequence values('EX2004');
insert into sequence values('EX2005');
insert into sequence values('EX2008');
Assuming your original table name is sequence with only one field, you can modify as per your needs
Try below
DECLARE #all TABLE
(
st varchar(20)
)
declare #start int
declare #end int
declare #str varchar(20)
set #start=2000 //define starting point
set #end=2010 //define end point
while(#start<#end)
BEGIN
SET #start=#start+1
set #str='EX'+cast(#start as varchar(20))
INSERT INTO #all VALUES (''+#str+'')
END
SELECT * from #all
except
select * from sequence
output
st
EX2003
EX2006
EX2007
EX2009
EX2010

if you need hard coded values in query then it can be done like (as you did not posted any code so here is a simple query). you can use IN() or NOT IN() in sql
select * from table where check_number not in ('EX2001','EX2002','EX2004' );

Since SQL engine is not mentioned, this answer is only for Oracle 11G
Option 1: With hierarchical queries
See Fiddle here
CREATE TABLE TEST1 ( A VARCHAR2 ( 9 ) );
INSERT INTO
TEST1
VALUES
( 'EX2001' );
INSERT INTO
TEST1
VALUES
( 'EX2002' );
INSERT INTO
TEST1
VALUES
( 'EX2004' );
COMMIT;
WITH TEST2
AS (SELECT
TO_NUMBER(SUBSTR ( A,
3 ))
AS A
FROM
TEST1)
SELECT
MIN_A
- 1
+ LEVEL
FROM
(SELECT
MIN ( A ) MIN_A,
MAX ( A ) MAX_A
FROM
TEST2)
CONNECT BY
LEVEL <= MAX_A
- MIN_A
+ 1
MINUS
SELECT A FROM TEST2;
Option 2: With Oracle analytics function
See Fiddle here
WITH T
AS (SELECT
TO_NUMBER(SUBSTR ( A,
3 ))
AS SNO,
SYSDATE AS SDATE
FROM
TEST1)
SELECT
SDATE,
SNO
+ 1
FIRST_MISSING,
DECODE ( NEXT_SNO
- 1,
SNO
+ 1, TO_NUMBER ( NULL ),
NEXT_SNO
- 1 )
LAST_MISSING
FROM
(SELECT
SDATE,
SNO,
LAG ( SNO )
OVER ( PARTITION BY SDATE
ORDER BY SNO )
LAST_SNO,
LEAD ( SNO )
OVER ( PARTITION BY SDATE
ORDER BY SNO )
NEXT_SNO
FROM
T)
WHERE
NVL ( NEXT_SNO,
SNO
+ 1 ) <> SNO
+ 1;

Related

Generate Row Count, increasing in 10,000 per row

I'm needing to return a generated ID where for each row it increases by 10,000.
For example, the ExpectedResult column in the below, and if there are more rows, it would increase by 10,000 each time.
Create Table #temp
(
ID uniqueidentifier,
ExpectedResult int
)
insert into #temp
(
ID,
ExpectedResult
)
select
NEWID(),
10000
union
select
NEWID(),
20000
union
select
NEWID(),
30000
union
select
NEWID(),
40000
union
select
NEWID(),
50000
select * from #temp
order by ExpectedResult
drop table #temp
I've found the example below, but I'm not sure how to increase the count by 10,000 each time
ROW_NUMBER() OVER (ORDER BY (SELECT 100))
If you are using SQL Server 2012 or later (including SQL Server 2017), you could create a numbering sequence using CREATE SEQUENCE.
To create SEQUENCE with increment of 10000, add the clause INCREMENT BY.
For example:
CREATE SEQUENCE Test.CountBy1
START WITH 10000
INCREMENT BY 10000
For more information, please consult this SQL Server documentation on CREATE SEQUENCE:
https://learn.microsoft.com/sql/t-sql/statements/create-sequence-transact-sql?view=sql-server-2017
you can use cte to generate N number for guids. Below is a sample cte to generate 100 rows for your guid.
Drop table #temp
Create Table #temp
(
ID uniqueidentifier,
ExpectedResult int
);
with cte as(
select newid() as new_id, 10000 as ctr
union all
select new_id, ctr + 10000 from cte where ctr/10000 < 100
)
insert into #temp
select * from cte option (MaxRecursion 0 );
select * from #temp;
You need to divide ROW_NUMBER() by 10000 and then multiply by 10000
You can write something like this
select *, rowNum10K = 10000 * (1 + (row_number() over (order by object_id)) / 10000)
from #temp
As suggested by Nick in the original question comments, have done this:
ROW_NUMBER() OVER (ORDER BY (SELECT 100))*10000
You can define the column as an identity to do this for you:
Create Table temp (
ID uniqueidentifier,
ExpectedResult int identity (10000, 10000)
);
insert into temp (ID)
select v.id
from (values (NEWID()), (NEWID()), (NEWID()), (NEWID()), (NEWID())) v(id);
Here is a db<>fiddle.

Adding Random Id for each unique value in table

I have the table like
ID RANDOM_ID
1 123
10 456
25 789
1 1112
55 1314
10 1516
I want the result to be like :
ID RANDOM_ID
1 123
10 456
25 789
1 123
55 1314
10 456
The same ID should have same random_ids. I'm using the update statement to generate the Random_IDs after creating the table.
CREATE TABLE [RANDOMID_TABLE]([ID] [int] NULL, [RANDOM_ID] [int] NULL)
GO
INSERT INTO [RANDOMID_TABLE] ([ID])
select distinct ABC_ID from RANDOMID_ABC
GO
******** This is the update statement for the RANDOM_ID column in
[RANDOMID_TABLE] table ************
UPDATE [RANDOMID_TABLE]
SET RANDOM_ID = abs(checksum(NewId()) % 1000000)
Is there something else that I need to add to the update statement?
Please advise.
Why would you use update for this? Just generate the values when you insert them:
insert into [RANDOMID_TABLE] (ID, RANDOM_ID)
select ABC_ID, abs(checksum(NewId()) % 1000000)
from RANDOMID_ABC
group by ABC_ID;
EDIT:
If your problem is collisions, then fix how you do the assignment. Just assign a number . . . randomly:
insert into [RANDOMID_TABLE] (ID, RANDOM_ID)
select ABC_ID, row_number() over (order by newid())
from RANDOMID_ABC
group by ABC_ID;
This is guaranteed to not return duplicates.
At a total guess, are you simpling wanting to UPDATE the table so that all the values of a specific ID to have the same value for Random_ID? Like this?
CREATE TABLE YourTable (ID int, Random_ID int);
INSERT INTO YourTable
VALUES(1 ,123),
(10,456),
(25,789),
(1 ,1112),
(55,1314),
(10,1516);
GO
WITH CTE AS(
SELECT ID,
Random_ID,
MIN(Random_ID) OVER (PARTITION BY ID) AS Min_Random_ID
FROM YourTable)
UPDATE CTE
SET Random_ID = Min_Random_ID;
GO
SELECT *
FROM YourTable;
GO
DROP TABLE YourTable;
Here is the script you need with use of temporary table (you need it to persist your random results for each unique ID):
DECLARE #Tbl TABLE (ID INT, RANDOM_ID INT)
INSERT #Tbl (Id) VALUES(1), (10), (25), (1), (55), (10)
SELECT Id, abs(checksum(NewId()) % 1000000) AS Random_Id INTO #distinctData FROM #Tbl GROUP BY Id
SELECT D.* FROM #Tbl T JOIN #distinctData D ON D.ID = T.ID
DROP TABLE #distinctData
Obviously, you don't need the first two rows where I create and initialize data table
Result:
Id Random_Id
1 354317
1 62026
10 532304
10 604768
25 874209
55 718643
You want one random value per ID. So one should think that the following would work:
with ids as
(
select distinct id
from randomid_table
)
, ids_with_rnd as
(
select id, abs(checksum(NewId()) % 1000000) as rnd
from ids
)
update randomid_table
set random_id =
(
select rnd
from ids_with_rnd
where ids_with_rnd.id = randomid_table.id
);
It doesn't however. SQL Server is somewhat buggy here and still creates different numbers for the same ID.
So, your best bet may be: do your update that does create different values (your original update statement). Then correct the data as follows:
update randomid_table
set random_id =
(
select min(random_id)
from randomid_table rt2
where rt2.id = randomid_table.id
);
Demo: https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=504236db66fba0f12dc7e407a51451f8

How to return only numbers from query where column is nvarchar

I have a simple query that is returning records where "column2" > 0
Here is the data in the database
Column1 Column2
1 123456789
2 123456781
3 13-151-1513
4 alsdjf
5
6 000000000
Her is the query
select column1, replace(a.Payroll_id,'-','')
from table1
where isnumeric(column2) = 1
I'd like to return the following:
Column1 Column2
1 123456789
2 123456781
3 131511513
This mean, I won't select any records when the column is blank (or null), will not return a row if it's not an integer, and will drop out the '-', and would not show row 6 since it's all 0.
How can I do this?
I think you can use something like this :
USE tempdb
GO
CREATE TABLE #Temp
(
ID INT IDENTITY
,VALUE VARCHAR(30)
)
INSERT INTO #Temp (VALUE) VALUES ('1213213'), ('1213213'), ('121-32-13'), ('ASDFASF2123')
GO
WITH CteData
AS
(
SELECT REPLACE(VALUE,'-','') as Valor FROM #Temp
)
SELECT * FROM CteData WHERE (ISNUMERIC(Valor) = 1 AND valor not like '%[0-0]%')
DROP TABLE #Temp
then you can apply validations for empty, NULL,0 etc
If you are using SQL2012 or above you can also use TRY_PARSE that is more selective in its parsing. This function will return NULL if a record can't be converted. You could use it like this:
CREATE TABLE #temp
(
ID INT IDENTITY ,
VALUE VARCHAR(30)
)
INSERT INTO #temp
( VALUE )
VALUES ( '1213213' ),
( '1213213' ),
( '121-32-13' ),
( 'ASDFASF2123' ),
( '0000000' )
SELECT ParsedValue
FROM #temp
CROSS APPLY ( SELECT TRY_PARSE(
Value AS INT ) AS ParsedValue
) details
WHERE ParsedValue IS NOT NULL
AND ParsedValue>0

Find missing numbers with SQL

In a large log file I have records containing the field INVNO (invoice-number).
The lowest and highest values are easy to find, BUT it looks like some numbers in between are not there.
Anyone got a trick with SQL, which can tell which numbers are missing within the number range?
use the following table valued function that takes 2 parameters : the min and max numbers,
and returns a list of missing number,
suppose your table name is YOUR_TABLE and the column name called InvNo
create FUNCTION [dbo].[MissingInvoiceNumbers]
(
#minPaym bigint,
#MaxPaym bigint
)
RETURNS #tmp table(numbers bigint)
AS
BEGIN
declare #n bigint --#minPaym bigint , #MaxPaym bigint,
declare #tmpAll table(Allnumbers bigint)
set #n= #minPaym
delete #tmp
delete #tmpAll
while (#n<=#MaxPaym)
begin
INSERT INTO #tmpAll
(AllNUMBERS)
VALUES (#n)
set #n=#n+1
end
INSERT INTO #tmp
(numbers)
SELECT Allnumbers
FROM #tmpAll
where Allnumbers not in (select distinct convert(bigint,InvNo) as InvoiceNum from YOUR_TABLE where
InvNo <> '' )
return
END
For oracle this should work. For any other database you just need to change way to generate the number sequence.
with vals as (
select rownum r
from dual
connect by rownum between {min} and {max}
)
select *
from vals v
left join {sometable} s on s.{someid} = v.r
where s.{someid} is null
The trick is just to generate numbers between min and max value, join table with invoices to this generated sequence and filter out everything that match.
Just join the table on itself...
DECLARE #tvp TABLE ( INVNO INT )
INSERT INTO #tvp
VALUES ( 1 ),
( 2 ),
( 3 ),
( 5 ),
( 6 ),
( 7 ),
( 8 ),
( 9 ),
( 10 ),
( 11 )
SELECT *
FROM #tvp;
SELECT t.INVNO + 1
FROM #tvp t
LEFT OUTER JOIN #tvp x ON x.INVNO = t.INVNO + 1
WHERE ISNULL(x.INVNO, 0) = 0;

Find missing numbers in a column

I have this column in T-SQL:
1
2
3
7
10
have SQl a function for detect the missing numbers in the sequence 4,5,6 and 8,9
I have try
something like
if ( a-b >1 ) then we have a missing number
with coalesce but i dont understand .
Thanks by any orientation
You can try this:
DELCARE #a
SET #a = SELECT MIN(number) FROM table
WHILE (SELECT MAX(number) FROM table ) > #a
BEGIN
IF #a NOT IN ( SELECT number FROM table )
PRINT #a
SET #a=#a+1
END
The following query will identify where each sequence starts and the number that are missing:
select t.col + 1 as MissingStart, (nextval - col - 1) as MissingSequenceLength
from (select t.col,
(select min(t.col) from t t2 where t2.col > t.col) as nextval
from t
) t
where nextval - col > 1
This is using a correlated subquery to get the next value in the table.
I know this is a late answer, but here is a query that uses recursive table expressions to get the missing values between the minimum and maximum values in a table:
WITH CTE AS
(
--This is called once to get the minimum and maximum values
SELECT nMin = MIN(t.ID), MAX(t.ID) as 'nMax'
FROM Test t
UNION ALL
--This is called multiple times until the condition is met
SELECT nMin + 1, nMax
FROM CTE
WHERE nMin < nMax
)
--Retrieves all the missing values in the table.
SELECT c.nMin
FROM CTE c
WHERE NOT EXISTS
(
SELECT ID
FROM Test
WHERE c.nMin = ID
)
This was tested with the following schema:
CREATE TABLE Test
(
ID int NOT NULL
)
INSERT INTO Test
Values(1)
INSERT INTO Test
Values(2)
INSERT INTO Test
Values(3)
INSERT INTO Test
Values(7)
INSERT INTO Test
Values(10)