I have a table with column name id and value. While data is being saved in sql server database, it sorts itself in random order, i.e id value 1,2,3,4,5,6,7,14,15,16,17,8,9,10 and likewise.
I need to retrieve data in 4 groups with each having 11 data in asc id order,
that is,
Group 1: 1-11
Group 2 : 12-22
Group 3 : 23-33
Group 4 : 33-44
I have tried query
Group 1:select top(11) * from tblCode order by id ASC
Group 2:SELECT top(22)* FROM tblCode except select top(11) * from tblCode order by id ASC
Group 3:SELECT top(33)* FROM tblCode except select top(22) * from tblQRCode order by id ASC
group 4:SELECT top(44)* FROM tblCode except select top(33) * from tblCode order by id ASC
What my problem is since data are sorted randomly while saving them into database, they are retrieved randomly.
Below is the screenshot of how my data are saved in database.
help me select data as above mentioned group.
Use OFFSET and FETCH rather than TOP.
E.g. Group two would be:
select *
from tblCode
order by id ASC
offset 11 rows
fetch next 11 rows only
Complete repro script:
declare #t table (ID int not null, Value varchar(93) not null);
;With Numbers as (
select ROW_NUMBER() OVER (ORDER BY so1.object_id) as n
from sys.objects so1,sys.objects so2,sys.objects so3
)
insert into #t (ID,Value)
select n,'PEC-' + CONVERT(varchar(93),n)
from Numbers
where n between 1 and 1000
select *
from #t
order by id ASC
offset 11 rows
fetch next 11 rows only
Result:
ID Value
----------- ---------
12 PEC-12
13 PEC-13
14 PEC-14
15 PEC-15
16 PEC-16
17 PEC-17
18 PEC-18
19 PEC-19
20 PEC-20
21 PEC-21
22 PEC-22
This also get your desired results. For other queries change 33 with other values, now it get values from 33 to 22.
WITH t AS
( SELECT ROW_NUMBER() OVER (ORDER BY id) AS row_num, *
FROM tblCode )
SELECT TOP 11 *
FROM t
WHERE row_num > 33
Try this,
select * from Table Name Order by ID
I hope I am not misunderstand:
--Group 1
SELECT *
FROM tblCode
WHERE id >= 1
AND id <= 11
ORDER BY id ASC
--Group 2
SELECT *
FROM tblCode
WHERE id >= 12
AND id <= 22
ORDER BY id ASC
--Group 3
SELECT *
FROM tblCode
WHERE id >= 23
AND id <= 33
ORDER BY id ASC
You can also save the increments in variable. Maybe something like this (i.e) you send param group no 3:
--Group 3
SELECT #Group = 3 --just for sample, param should sent From application
SELECT #lastIndex = 3*11
SELECT #indexStart = #lastIndex - 10
SELECT *
FROM tblCode
WHERE id >= #indexStart
AND id <= #lastIndex
ORDER BY id ASC
Related
I have a table bawe_services. i want to fetch all data that match with given keys
like i have fields
id | Service_id |bawe_id
1 2 2
2 3 3
3 2 3
if i pass service =2 i need all record of service_id=2 if i pass service=1,2,3 than i want 0 rows because 1 service is not given by any bawe so. i got 0 rows.
I use this query
select * from aspnet_bawe_services where ser_id in(1,2,3)
Thanx in advance
The count of the parameters in the "in" statement must match the having equal number.
select bawe_id from [dbo].[aspnet_bawe_services]
where Service_id in (2)
group by bawe_id
having count(Service_id)=1;
bawe_id
-----------
2
3
select bawe_id from [dbo].[aspnet_bawe_services]
where Service_id in (2,3)
group by bawe_id
having count(Service_id)=2;
bawe_id
-----------
3
select bawe_id from [dbo].[aspnet_bawe_services]
where Service_id in (1,2,3)
group by bawe_id
having count(Service_id)=3;
bawe_id
-----------
(0 row(s) affected)
TRY THIS: It's really tedious but unique requirement and I think to accomplish this, we have to use function
1-Function returns distinct count of service_id
2-Function to split comma separated value and return in table format
--Function returns distinct count of service_id
CREATE FUNCTION [dbo].[getCount](#service_id varchar(500))
RETURNS INT
AS
BEGIN
DECLARE #count int
SELECT #count = COUNT(DISTINCT(t.service_id))
FROM tmptos t
INNER JOIN [dbo].[SplitValue](#service_id, ',') tt on t.service_id = tt.items
RETURN #count
END;
--Function to split comma separated value and return in table format
--Function copied from
--separate comma separated values and store in table in sql server
CREATE FUNCTION [dbo].[SplitValue](#String varchar(MAX), #Delimiter char(1))
RETURNS #temptable TABLE (items VARCHAR(MAX))
AS
BEGIN
DECLARE #idx int
DECLARE #slice varchar(8000)
SELECT #idx = 1
if len(#String)<1 or #String is null return
WHILE #idx!= 0
BEGIN
set #idx = charindex(#Delimiter,#String)
IF #idx!=0
set #slice = left(#String,#idx - 1)
else
set #slice = #String
IF(LEN(#slice)>0)
INSERT INTO #temptable(Items) values(#slice)
SET #String = right(#String,len(#String) - #idx)
IF LEN(#String) = 0 break
END
RETURN
END;
--Table with Sample Data
create table tmptos(id int, Service_id int, bawe_id int)
insert into tmptos values
(1, 2, 2),
(2, 3, 3),
(3, 2, 3)
declare #service_id varchar(50) = '2,3'
select *
from tmptos t
inner join [dbo].[SplitValue](#service_id, ',') tt on t.Service_id = tt.items
where [dbo].[getCount](#service_id) = (select count(distinct(items)) from [dbo].[SplitValue](#service_id, ','))
OUTPUT:
id Service_id bawe_id items
1 2 2 2
2 3 3 3
3 2 3 2
It's bit lengthy but works perfectly.
select * from aspnet_bawe_services
where Service_id in (1,2,3)
and
( select count(distinct Service_id) from aspnet_bawe_services where Service_id in (1,2,3) ) = 3
last number in query (in this case "3") is elements count, which you have in IN list.
You can get the service ids that you want using group by and having:
select service_id
from t
where bawe_id in (1, 2, 3)
group by service_id
having count(distinct bawe_id) = 3;
The "= 3" is the number of ids in the IN list.
You can then use in or join or exists to get the full records:
select t.*
from t
where t.service_id in (select service_id
from t
where bawe_id in (1, 2, 3)
group by service_id
having count(distinct bawe_id) = 3
);
I am basically trying to run these two queries:
SELECT * FROM ProductTable;
SELECT CAST(CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END AS BIT)
FROM UserTable WHERE id = 41;
Both queries work properly. The first one returns me all the data in ProductTable. The second query returns me either 1 or 0 after checking if the row ID 41 exists
Running them together:
SELECT * FROM ProductTable SELECT CAST(CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END AS BIT)
FROM UserTable WHERE id = 41
However, when I run this, the second query does not return any value, this is because I have not set a SQL variable name to it.
How can I set a Variable name to the second query such that I can read that value when reading the SQL response?
DECLARE #val BIT
SELECT #val = CAST(CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END AS BIT)
FROM UserTable WHERE id = 41
SELECT P.*, #val FROM ProductTable P
If you need either 1 or 0 after checking if the row ID 41 exists then (following Pinwar13 answer) this code performs better, needn't count all rows
DECLARE #val BIT = CASE WHEN EXISTS (SELECT 1 FROM UserTable WHERE id = 41)
THEN 1 ELSE 0 END;
SELECT P.*, #val FROM ProductTable P
Try like this,
SELECT *
,(
SELECT CAST(CASE
WHEN COUNT(*) > 0
THEN 1
ELSE 0
END AS BIT)
FROM UserTable
WHERE id = 41
) AS UserCount
FROM ProductTable;
you can use cross apply also..
SELECT p.*,t.[BIT] FROM ProductTable p
CROSS APPLY (SELECT CAST(CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END AS [BIT])
FROM UserTable WHERE id = 41)t
getName_as_Rows is an array which contains some names.
I want to set an int value to 1 if record found in data base.
for(int i = 0; i<100; i++)
{
using (var command = new SqlCommand("select some column from some table where column = #Value", con1))
{
command.Parameters.AddWithValue("#Value", getName_as_Rows[i]);
con1.Open();
command.ExecuteNonQuery();
}
}
I am looking for:
bool recordexist;
if the above record exist then bool = 1 else 0 with in the loop.
If have to do some other stuff if the record exist.
To avoid making N queries to the database, something that could be very expensive in terms of processing, network and so worth, I suggest you to Join only once using a trick I learned. First you need a function in your database that splits a string into a table.
CREATE FUNCTION [DelimitedSplit8K]
--===== Define I/O parameters
(#pString VARCHAR(8000), #pDelimiter CHAR(1))
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
--===== "Inline" CTE Driven "Tally Table" produces values from 0 up to 10,000...
-- enough to cover VARCHAR(8000)
WITH E1(N) AS (
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
), --10E+1 or 10 rows
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS (--==== This provides the "zero base" and limits the number of rows right up front
-- for both a performance gain and prevention of accidental "overruns"
SELECT 0 UNION ALL
SELECT TOP (DATALENGTH(ISNULL(#pString,1))) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
),
cteStart(N1) AS (--==== This returns N+1 (starting position of each "element" just once for each delimiter)
SELECT t.N+1
FROM cteTally t
WHERE (SUBSTRING(#pString,t.N,1) = #pDelimiter OR t.N = 0)
)
--===== Do the actual split. The ISNULL/NULLIF combo handles the length for the final element when no delimiter is found.
SELECT ItemNumber = ROW_NUMBER() OVER(ORDER BY s.N1),
Item = SUBSTRING(#pString,s.N1,ISNULL(NULLIF(CHARINDEX(#pDelimiter,#pString,s.N1),0)-s.N1,8000))
FROM cteStart s
GO
Second, concatenate your 100 variables into 1 string:
"Value1", "Value 2", "Value 3"....
In Sql Server you can just join the values with your table
SELECT somecolumn FROM sometable t
INNER JOIN [DelimitedSplit8K](#DelimitedString, ',') v ON v.Item = t.somecolumn
So you find 100 strings at a time with only 1 query.
Use var result = command.ExecuteScalar() and check if result != null
But a better option than to loop would be to say use a select statement like
SELECT COUNT(*) FROM TABLE WHERE COLUMNVAL >= 0 AND COLUMNVAL < 100,
and run ExecuteScalar on that, and if the value is > 0, then set your variable to 1.
I have the following table structure
| id | parentID | count1 |
2 -1 1
3 2 1
4 2 0
5 3 1
6 5 0
I increase count values from my source code, but i also need the increase in value to bubble up to each parent id row until the parent id is -1.
eg. If I were to increase count1 on row ID #6 by 1, row ID #5 would increase by 1, ID #3 would increase by 1, and ID #2 would increase by 1.
Rows also get deleted, and the opposite would need to happen, basically subtracting the row to be deleted' value from each parent.
Thanks in advance for your insight.
I'm using SQL Server 2008, and C# asp.net.
If you really want to just update counts, you could want to write stored procedure to do so:
create procedure usp_temp_update
(
#id int,
#value int = 1
)
as
begin
with cte as (
-- Take record
select t.id, t.parentid from temp as t where t.id = #id
union all
-- And all parents recursively
select t.id, t.parentid
from cte as c
inner join temp as t on t.id = c.parentid
)
update temp set
cnt = cnt + #value
where id in (select id from cte)
end
SQL FIDDLE EXAMPLE
So you could call it after you insert and delete rows. But if your count field are depends just on your table, I would suggest to make a triggers which will recalculate your values
You want to use a recursive CTE for this:
with cte as (
select id, id as parentid, 1 as level
from t
union all
select cte.id, t.parentid, cte.level + 1
from t join
cte
on t.id = cte.parentid
where cte.parentid <> -1
) --select parentid from cte where id = 6
update t
set count1 = count1 + 1
where id in (select parentid from cte where id = 6);
Here is the SQL Fiddle.
once there are new data insert to my DB my rcount will increase by 1, what am i trying to do is to display latest inserted record to users, but i cant get my expected result
rCount in my datebase
1
2
3
4
5
output
5
4
3
1
2
expected output
5
4
3
2
1
"SELECT *, ROW_NUMBER() OVER (ORDER BY rCount DESC) AS 'RowNumber'
FROM [MovieListTable]"
Instead of using the row number you should introduce a numeric primary key (i.e. Id) and make it an Identity column. Now you can just select the row that has the maximum Id value:
select top 1 * from MovieListTable order by Id desc
Or to get all rows:
select * from MovieListTable order by Id desc