Obtain the missing number [duplicate] - c#

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Find the smallest unused number in SQL Server
I have this table in Sql server
ID | LetterID | LetterName
ID => int and identity
LetterID => int and unique and NotNull
LetterName => string
LetterID fill from my C# application and user set number for it.for example 1,2,3,4,5,...,100,.. (increment an unit for each row) and now my LetterID is 100 but Sometimes user delete one row from table for example delete row where LetterID is 50, now for insert new row (in application) I suggested to him LetterID chose 50, How can I get the missing numbers from table?

var output = Enumerable.Range(1, list.Max(item => item.LetterID))
.Except(list.Select(item => item.LetterID))

get the blank/missing row
SELECT TOP 1 x.LetterID +1
FROM tablename x
WHERE NOT EXISTS(SELECT * FROM tablename xx WHERE xx.LetterID = x.LetterID + 1)
ORDER BY x.LetterID

select t1.ID, t1.LetterID-1
from yourtable t1
left join yourtable t2
on t1.LetterID = t2.LetterID+1
and t1.ID = t2.ID
where t2.ID is null
and t1.LetterID>(select MIN(LetterID) from yourtable where ID = t1.ID)

;with cte as
(
select max(LetterID) as id from your_table
union all
select id-1 from cte where id>1
)
select cte.id as LetterID
from cte
left join your_table yt on cte.id=yt.LetterID
where yt.id is null
order by cte.id

Related

GROUP BY, ORDER BY and taking first in LINQ

Suppose I have a table with two columns:
TABLE A
-------
ProjectID NUMBER
STATUS VARCHAR2(6) // either 'CLOSED' or 'NEW'
There could be maximum two entries for a ProjectID with the two possible values of STATUS and the combination (ProjectID, STATUS) is unique.
I need to select only those ProjectID's that have status 'NEW'. Also, if for a projectID, there are two entries with different statuses (NEW and CLOSED), I don't want it in the output.
I tried using group by, then ordering the resultset descending (so as to get 'NEW' row for a project ID first) and then taking the first row in LINQ, similar to this:
var query = (from a in context.A.Where(o => o.STATUS == 'NEW')
group a by a.ProjectID into groups
select groups.OrderByDescending(o => o.ProjectID)
.ThenBy(o => o.STATUS)
.FirstOrDefault());
Butt it's resulting into an "APPLY" clouse in the query which is resulting into an error. Apparantly, Oracle 10g doesn't support it.
Any help is appreciated.
Something like this, perhaps?
SQL> with test (projectid, status) as
2 (select 1, 'new' from dual union -- should be returned
3 select 2, 'new' from dual union
4 select 2, 'closed' from dual union
5 select 3, 'closed' from dual union
6 select 4, 'new' from dual -- should be returned
7 )
8 select projectid
9 from test
10 group by projectid
11 having min(status) = max(status)
12 and min(status) = 'new';
PROJECTID
----------
1
4
SQL>
Proper tu use having count(distinct STATUS=1) :
create table tableA( ProjectID int, STATUS varchar2(10) );
insert all
into tableA values(1 ,'NEW')
into tableA values(1 ,'CHANGED')
into tableA values(2 ,'NEW')
into tableA values(3 ,'CHANGED')
select * from dual;
/
select * from
(
select ProjectID, max(STATUS) STATUS
from tableA
group by ProjectID
having count(distinct STATUS)=1
)
where STATUS = 'NEW';
I believe I have accomplished what you want, using a subquery in LINQ.
var query = (from a in context.A
where (from b in context.A
where b.ProjectID == a.ProjectID
select new { a.ProjectID, a.STATUS }).Distinct().Count() == 0
&& a.STATUS == "NEW"
select a.ProjectID).ToList();
Essentially, the outer query just makes sure that each a record has a NEW status, and the inner query makes sure that there are no two distinct records with the given ProjectID, because if there are, one is CLOSED. I avoided using a GROUP BY since you said your database does not support LINQ's way of doing it.
I hope I understood your problem correctly, and I hope this helps!

DISTINCT query not working its give me repeated columns on output

Buddy
i have one query of MSSQL.
that is like this..
SELECT DISTINCT resource.locationurl,
resource.resourcename,
resource.anwserid,
checktotal.total
FROM resource
INNER JOIN (SELECT Count(DISTINCT anwserid) AS total,
resourcename
FROM resource AS Resource_1
WHERE ( anwserid IN (SELECT Cast(value AS INT) AS Expr1
FROM dbo.Udf_split(#sCategoryID, ',')
AS
udf_Split_1) )
GROUP BY resourcename) AS checktotal
ON resource.resourcename = checktotal.resourcename
WHERE ( resource.anwserid IN (SELECT Cast(value AS INT) AS Expr1
FROM dbo.Udf_split(#sCategoryID, ',') AS
udf_Split_1)
)
AND ( checktotal.total = #Total )
ORDER BY resource.resourcename
I run this query but its give me repeated column of Resource.LocationURL.
you can check it live hear http://www.ite.org/visionzero/toolbox/default2.aspx
check in above link where you can fire select some category but result was not distinct..
i try most of my but now i am out of mind please help me with this.
You misunderstand what DISTINCT means when you are fetching more than one column.
If you run this query:
SELECT DISTINCT col1, col2 FROM table
You are selected every different combination. An acceptable result would be
value 1_1, value 2_1
value 1_1, value 2_2,
value 2_1, value_2_1
In this example, value 1_1 appears twice, but the two columns combined are unique.
My guess is that you are actually attempting to perform a grouping:
SELECT resource.locationurl,
resource.resourcename,
resource.anwserid,
Sum(checktotal.total)
FROM resource
INNER JOIN (SELECT Count(DISTINCT anwserid) AS total,
resourcename
FROM resource AS Resource_1
WHERE ( anwserid IN (SELECT Cast(value AS INT) AS Expr1
FROM dbo.Udf_split(#sCategoryID, ',')
AS
udf_Split_1) )
GROUP BY resourcename) AS checktotal
ON resource.resourcename = checktotal.resourcename
WHERE ( resource.anwserid IN (SELECT Cast(value AS INT) AS Expr1
FROM dbo.Udf_split(#sCategoryID, ',') AS
udf_Split_1)
)
AND ( checktotal.total = #Total )
GROUP BY resource.locationurl,
resource.resourcename,
resource.anwserid
First of all, the site you linked doesn't do anything.
Second, DISTINCTensures unique rows. It will not make the values in all the columns unique as well. Just think about it! How would it work? You have two rows with the same locationurl field, but with otherwise distinct elements. Which one do you not include?
Lastly, please take greater care in phrasing your questions.
as I see your query is select DISTINCT on multi columns,
so if any record has at least one col difference then it pass the DISTINCT condition
Ex:
record1 : locationurl | resourcename | anwserid | Sum(checktotal.total)
loc1 res1 1 100
record2 : locationurl | resourcename | anwserid | Sum(checktotal.total)
loc1 res1 2 100

SQL Server : how to detect unregarded values from a range of integers

I have a problem, in example: I have a range of ids of integers (from 1 to 1000), this range supposed to be ids in a SQL Server table, and I want to detect which numbers of this range are not in the table, and sorry for my bad english, thank you
another simpler option would be to use the following query
SELECT number
FROM master..spt_values
WHERE number BETWEEN 1 AND 1000
AND NOT EXISTS ( SELECT 1
FROM Your_Table t --<-- your table where you are checking
WHERE t.ID = number) -- the missing values
GROUP BY number
The above solution is only good if you are looking for around 1000 values. For more values you would need to modify it little bit, something like
-- Select the maximum number or IDs you want to check
DECLARE #Max_Num INT = 10000;
;WITH CTE AS
(
SELECT TOP (#Max_Num) ROW_NUMBER() OVER ( ORDER BY (SELECT NULL)) numbers
FROM master..spt_values v1 cross join master..spt_values v2
)
SELECT c.numbers
FROM CTE c
WHERE NOT EXISTS (SELECT 1
FROM Your_table t
WHERE t.ID = c.numbers)
One way to find "holes" is to generate a list of all possible values and then look for the ones that aren't there. If you can survive with a list of a missing value and then the number of subsequent values following it, you can do this with another method.
SQL Server 2012+ supports lead() and lag(). The following gets almost everything, except for initial missing values:
select t.id + 1 as missingid,
(coalesce(t.nextid, 1000) - t.id - 1) as nummissing
from (select t.*, lead(t.id) over (order by t.id) as nextid
from table t
t.id between 1 and 1000
) t
where t.nextid > t.id + 1 or
(t.nextid is null and t.id <> 1000)
You can get these with a little piece of special logic:
select (case when t.previd is null then 1
else t.id + 1
end) as missingid,
(case when t.previd is null then t.id - 1
else (coalesce(t.nextid, 1000) - t.id - 1)
end) as nummissing
from (select t.*, lead(t.id) over (order by t.id) as nextid,
lag(t.id) over (order by t.id) as previd
from table t
where t.id between 1 and 1000 and
) t
where (t.nextid > t.id + 1 or
(t.nextid is null and t.id <> 1000)
(t.previd is null and t.id <> 1)
)
This sounds like one of the many scenarios where it is helpful to have a numbers table:
SELECT *
FROM lkp_Numbers a
WHERE NOT EXISTS (SELECT 1
FROM YourTable b
WHERE a.num = b.Id)
AND num <= 1000
I use this to create a numbers table:
DROP TABLE lkp_Numbers
DECLARE #RunDate datetime
SET #RunDate=GETDATE()
SELECT TOP 1000 IDENTITY(int,1,1) AS Num
INTO lkp_Numbers
FROM sys.objects s1, sys.objects s2, sys.objects s3
ALTER TABLE lkp_Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Num)
That method for creating a numbers table was found here: What is the best way to create and populate a numbers table?

Insert and Update an array of dynamic length into a table

My table is
(id int,property varchar)
Suppose I want to insert {3, 'a, b, c'}. How can I do it in a stored procedure?
The table entry would be:
id property
3 a
3 b
3 c
Also when i want to update my id=3 row by {3, 'ab, b, bg, ht'} . What would be the stored procedure for this insert and update operation? My table entries should become
id property
3 ab
3 b
3 bg
3 ht
sample table:
create table yourtable (id int,property varchar(5))
Procedure for that table:
create procedure p_test
(
#id int,
#prolist varchar(2000)
) as
begin
;with x as
(
SELECT * FROM yourtable WHERE id = #ID
)
MERGE INTO
x t1
using
(SELECT #id id, ltrim(t.c.value('.', 'VARCHAR(2000)')) property
FROM (
SELECT x = CAST('<t>' +
REPLACE(#prolist, ',', '</t><t>') + '</t>' AS XML)
) a
CROSS APPLY x.nodes('/t') t(c)) t2 on t1.id = t2.id and t1.property = t2.property
when not matched then INSERT (id,property)
VALUES(t2.id, t2.property)
when matched
THEN UPDATE SET t1.id = t2.id
WHEN NOT MATCHED BY SOURCE THEN DELETE
;
end
Testing:
exec p_test 3, 'b,c'
select * from yourtable
exec p_test 3, 'a,b,c'
select * from yourtable
exec p_test 3, 'a,c'
select * from yourtable
exec p_test 4, 'g,h'
select * from yourtable
Result:
id property
3 b
3 c
id property
3 b
3 c
3 a
id property
3 c
3 a
id property
4 g
3 c
3 a
4 h
EDIT:
in order to update a new column use this table:
create table yourtable (id int,property varchar(5), is_active bit default 1)
Use this procedure:
alter procedure p_test
(
#id int,
#prolist varchar(2000)
) as
begin
;with x as
(
SELECT * FROM yourtable WHERE id = #ID
)
MERGE INTO
x t1
using
(SELECT #id id, ltrim(t.c.value('.', 'VARCHAR(2000)')) property
FROM (
SELECT x = CAST('<t>' +
REPLACE(#prolist, ',', '</t><t>') + '</t>' AS XML)
) a
CROSS APPLY x.nodes('/t') t(c)) t2 on t1.id = t2.id and t1.property = t2.property
when not matched then INSERT (id,property, is_active)
VALUES(t2.id, t2.property, 1)
when matched
THEN UPDATE SET t1.id = t2.id, is_active = 1
WHEN NOT MATCHED BY SOURCE THEN
UPDATE SET t1.is_active = 0
;
end
First one:
insert into <tableName>(id, property) values(3, 'a');
insert into <tableName>(id, property) values(3, 'b');
insert into <tableName>(id, property) values(3, 'c');
Second issue:
update <tableName> set property='ab' where property = 'a';
update <tableName> set property='bg' where property = 'c';
insert into <tableName>(id, property) values(3, 'ht');
And now, a question: are you sure this is what your problem needs? Usually, when we call a column id we want it to be an identifier, that is, unique for each row. This may be a little bit off topic, but just in case...
There should be an id/primary key which will be unique. Profide any unique field and update records on the base of that unique field. Or you can make property unique or pair of id and property unique.
If I understood well, you could do something similar to this:
Insert INTO #tempTable
SELECT 3, * FROM dbo.splitstring('a,b,c,d')
It's just a pseudocode and you should do it inside your stored procedure.
If this is the right approach you have to take a look at this: T-SQL split string

LINQ to Entities find top records from ordered groupings

I have a problem that I know how to solve in SQL but not with Linq to Entities.
My data looks like this:
ID GROUP TIMESTAMP
-- ----- ---------
1 A 2011-06-20
2 A 2011-06-21
3 B 2011-06-21
4 B 2011-06-22
5 B 2011-06-23
6 C 2011-06-30
I want to retrieve all the Entity objects (not just the ID) such that I am only getting the most recent record from each group. (ie. the records with ids 2, 5, 6)
In SQL I would do something like this:
SELECT * FROM my_table a
WHERE a.timestamp =
(SELECT MAX(timestamp) FROM my_table b
WHERE a.group = b.group)
(For the sake of this question you can assume that timestamp is unique within each group).
I'd like to do this query against a WCF Data Service using Linq to Entities but I can't seem to have a nested query that references the outside query like this. Can anyone help?
Possibly not as clean and efficient as the hand written version but here's what I came up with
var q = from a in db.MyEntities
where a.Timestamp == (from b in db.MyEntities
where b.Group == a.Group
select b.Timestamp).Max()
select a;
which translates into this SQL
SELECT
[Project1].[Id] AS [Id],
[Project1].[Group] AS [Group],
[Project1].[Timestamp] AS [Timestamp]
FROM ( SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Group] AS [Group],
[Extent1].[Timestamp] AS [Timestamp],
[SSQTAB1].[A1] AS [C1]
FROM [MyEntities] AS [Extent1]
OUTER APPLY
(SELECT
MAX([Extent2].[Timestamp]) AS [A1]
FROM [MyEntities] AS [Extent2]
WHERE [Extent2].[Group] = [Extent1].[Group]) AS [SSQTAB1]
) AS [Project1]
WHERE [Project1].[Timestamp] = [Project1].[C1]
Hi try to use linqer that will convert your sql statements to linq query.
Linqer
Best Regards
This should work:
var query = db.my_table
.GroupBy(p=>p.group)
.Select(p=>p.OrderByDescending(q=>q.timestamp).First());
Here you go.A simple way to do.
var result = (from x in my_table
group x by x.Group into g
select new
{
g.Key,
timestamp = g.Max(x => x.TimeStamp),
g //This will return everything in g
});

Categories