How to ROWCOUNT_BIG() value with union all - sql

I have the following query in SQL Server. How do I get the number of rows of previous select query as following format?
Sample Query
select ID, Name FROM Branch
UNION ALL
SELECT ROWCOUNT_BIG(), ''
Sample Output

If you use a CTE you can count the rows and union all together:
with cte as (
select ID, [Name]
from dbo.Branch
)
select ID, [Name]
from cte
union all
select count(*) + 1, ''
from cte;

I think you want to see total count of the select statement. you can do this way.
CREATE TABLE #test (id int)
insert into #test(id)
SELECT 1
SELECT id from #test
union all
SELECT rowcount_big()
Note: Here, the ID will be implicitly converted to BIGINT datatype, based on the datatype precedence. Read more

Presumably, you are running this in some sort of application. So why not use ##ROWCOUNT?
select id, name
from . . .;
select ##rowcount_big; -- big if you want a bigint
I don't see value to including the value in the same query. However, if the underlying query is an aggregation query, there might be a way to do this using GROUPING SETS.

Here are two ways. It's better to use a CTE to define the row set so further table inserts don't interfere with the count. Since you're using ROWCOUNT_BIG() these queries use COUNT_BIG() (which also returns bigint) to count the inserted rows. In order to make sure the total always appears as the last row an 'order_num' column was added to the SELECT list and ORDER BY clause.
drop table if exists #tTest;
go
create table #tTest(
ID int not null,
[Name] varchar(10) not null);
insert into #tTest values
(115, 'Joe'),
(116, 'Jon'),
(117, 'Ron');
/* better to use a CTE to define the row set */
with t_cte as (
select *
from #tTest)
select 1 as order_num, ID, [Name]
from t_cte
union all
select 2 as order_num, count_big(*), ''
from t_cte
order by order_num, ID;
/* 2 separate queries could give inconsistent result if table is inserted into */
select 1 as order_num, ID, [Name]
from #tTest
union all
select 2 as order_num, count_big(*), ''
from #tTest
order by order_num, ID;
Both return
order_num ID Name
1 115 Joe
1 116 Jon
1 117 Ron
2 3

Related

SQL : How to find the count of an particular category values from an column with string values

I have a SQL Table called "category" looks like this
id | category
--------------
1 | 3,2
2 | 1
3 | 4,3,2
4 | 2,1
5 | 1,4
6 | 2,3,4
There are multiple category id's in the column "category", I need to find the count of an particular category values.
Current method I am using is:
select count(distinct(Category)) AS coldatacount from table_name
It gives the count of all the distinct values WHERE as I need to get
the count of all the particular category_id's separately.
if you are trying to get the Category Ids in comma delimited, you can use the string_split function to get distinct category_id
with cte as (
select 1 as id, '3,2' as category union all
select 2, '1' union all
select 3, '4,3,2' union all
select 4, '2,1' union all
select 5, '1,4' union all
select 6, '2,3,4'
)select count(distinct(value)) as category from cte
cross apply string_split(cte.category, ',');
I assumed that #neeraj04 may be looking for count of all Id in the category, continuing with #METAL code:
CREATE TABLE YourTable
(
Id INT IDENTITY,
[Category] VARCHAR(50)
);
INSERT YourTable VALUES ('3,2'), ('1'), ('4,3,2'), ('2,1'), ('1,4'), ('2,3,4');
SELECT CAST(value AS INT) AS category -- Value is string ouptut
, COUNT([value]) AS IdCount
FROM YourTable yt
CROSS APPLY string_split(yt.Category, ',')
GROUP BY [value]
ORDER BY category;
This is a horrible data model. You should not be storing multiple values in a string. You should not be storing numbers as strings.
Sometimes we are stuck with other people's really, really bad decisions. One approach is to split the string and count:
select t.*, cnt
from t cross apply
(select count(*) as cnt
from string_split(t.category) s
) s;
The other is to count commas:
select t.*,
(1 + len(t.category) - len(replace(t.category, ',', '')) as num_elements
Select Count(Value) from (Select Value from Table_Name a Cross Apply
string_split(a.Category, ','))ab Where Value=1

SQL Server query for getting single value from each column into a single column

I'll start directly by explaining with an example. Suppose I have a table which has 3 columns as shown.
Now what I am trying to achieve is, I want the first values of each individual column into a single column. So it would be something like this,
I have tried a few queries here including using TOP 1 and other incorrect ways. But I am still missing something here to achieve the exact output.
Need some guidance here on how to achieve this. Thank you.
SAMPLE TABLE
SELECT * INTO #TEMP
FROM
(
SELECT 1 BATCH_ID,'AAA' ASSIGNMENTTITLE,'FILE' ASSIGNMENTTYPE
UNION ALL
SELECT 1,'AAA1','FILE'
UNION ALL
SELECT 1,'AAA','FILE'
)TAB
If you need the second row specifically you can do the below
QUERY
;WITH CTE AS
(
-- Order row according to default format
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT(0))) RNO,*
FROM #TEMP
)
SELECT CAST(BATCH_ID AS VARCHAR(20)) FROM CTE WHERE RNO=2
UNION ALL
SELECT ASSIGNMENTTITLE FROM CTE WHERE RNO=2
UNION ALL
SELECT ASSIGNMENTTYPE FROM CTE WHERE RNO=2
Click here to view result
UPDATE
Since there are 3 items in each record, it can be puzzled unless and otherwise an a column is for each items in a record.
;WITH CTE AS
(
-- Order row according to default format
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT(0))) RNO,*
FROM #TEMP
)
SELECT CAST(BATCH_ID AS VARCHAR(20)),RNO
FROM CTE
UNION ALL
SELECT ASSIGNMENTTITLE,RNO
FROM CTE
UNION ALL
SELECT ASSIGNMENTTYPE,RNO
FROM CTE
ORDER BY RNO
Click here to view result
You can use the concat() function to create a column consisting of all the desired values
More info here
Simply you can try this. If want specific for a row use rowid. For all columns Use unpivot
create table #temp(id int, name varchar(100), title varchar(100))
insert into #temp values(1,'aaa','file')
insert into #temp values(1,'aaas','filef')
insert into #temp values(1,'aaaww','filefs')
select * from #temp
select top 1 cast(id as varchar) title from #temp
union
select top 1 name from #temp
union
select top 1 title from #temp
drop table #temp
This might help you
select top 1 convert(varchar(10), batch_id) ASSIGNMENTTITLE from table
union all
select top 1 ASSIGNMENTTITLE from table
union all
select top 1 ASSIGNMENTTYPE from table
If this is really what you want: "I want the first values of each individual column into a single column" it would be:
select ASSIGNMENTTITLE
from (
select min(convert(varchar(10), batch_id)) ASSIGNMENTTITLE,
1 ColOrder from table
union all
select min(ASSIGNMENTTITLE),
2 ColOrder from table
union all
select min(ASSIGNMENTTYPE),
3 ColOrder from table
) as data
order by ColOrder

Alternating Results of two SQL queries

This is probably not possible, but is there a way to output the results of two queries in alternating lines on a table?
For example if I have two tables that are trying to show one widget vs all of the widgets in its category, I would output each widget followed by the category averages, followed by widget 2 with its category averages in the next line. This would result in 4 lines. This is all assuming that widgets and their category averages are in two separate tables.
Sorry if this was confusing, I can clarify if I need to. I'm just trying to make it very simple for the final application to display in C#. It would probably be easier to do in the actual application but I'm not very familiar with C#...
First - as said in the comments - If you have a field to order by you can use one select with union and order by. and you are done.
Even if not (different ordering on each query) it's stil possible (assuming the two queries have the same exact schema):
SELECT *
FROM (SELECT ROW_NUMBER() OVER (ORDER BY ColA) OrderA,1 OrderB,*
FROM A
UNION ALL
SELECT ROW_NUMBER() OVER (ORDER BY ColB) + 1 OrderA,2 OrderB, *
FROM B) C
ORDER BY OrderA, OrderB
Disclaimer - I don't think it's a database operation.
This is possible using two table variables, two sort columns in each and a union all, but I would recommend that you join the two tables together and have one row for each widget (can have many columns one for category averages) and manage the display aspects of the design on the C# side
If you have two temporary tables with identity columns, you can select a UNION of both tables with a careful manipulation of the row number:
declare #linesA table
(
lineid int identity(1,1) primary key clustered,
line varchar(80)
)
declare #linesB table
(
lineid int identity(1,1) primary key clustered,
line varchar(80)
)
insert into #linesA (line)
select 'A - 1'
union select 'A - 2'
union select 'A - 3'
insert into #linesB (line)
select 'B - 1'
union select 'B - 2'
union select 'B - 3'
select
lineid * 2 as RowNum,
line from #linesA
union select
lineid * 2 + 1 as RowNum,
line from #linesB
order by RowNum
If you don't have an identity column, then create one with ROW_NUMBER() like this:
select
row_number() over (order by line) * 2 as RowNum,
line from #linesA
union select
(row_number() over (order by line) * 2) + 1 as RowNum,
line from #linesB
order by RowNum
as updated in the comments.
first CTE is to generate only ODD and Even Numbers
remember that by default max allowed recursion is 100.
so we are setting value of #I to the number of records in to first table.
also notice the "OPTION (MAXRECURSION 0);" which is required if number of records happen to be more that 100 and in that case recursion happen that many times.
DECLARE #widget TABLE
(
widgetID INT
,widgetName sysname
,WidgetType sysname
)
DECLARE #categoryAvg TABLE
(
WidgetType sysname
,categoryAvg sysname
)
INSERT INTO #widget( widgetID, widgetName,WidgetType )
SELECT 1,'widget1','Wtype1'
UNION ALL SELECT 2,'widget2','Wtype1'
UNION ALL SELECT 2,'widget3','Wtype2'
UNION ALL SELECT 2,'widget4','Wtype2'
INSERT INTO #categoryAvg( WidgetType, categoryAvg )
SELECT 'Wtype1',10 UNION ALL SELECT 'Wtype2',20
declare #i int=100--MAX 100 ByDefault
declare #StartOdd int=1 --To generate ODD numbers
declare #StartEven int=2 --To generate EVEN numbers
SELECT #i = COUNT(*) From #widget
;WITH CTE_OE(Rowid,OddNum,EvenNum)
as
(
select 1,#StartOdd,#StartEven
union all
select t1.rowid+1,t1.OddNum+2,t1.EvenNum+2
from CTE_OE t1
where t1.rowid<#i
),
CTE_1(WidgetType,OutputColumn,RowID)
AS
(
SELECT t1.WidgetType,t1.OutputColumn,t2.OddNum
FROM
(
SELECT WidgetType
,widgetName As OutputColumn
,ROW_NUMBER() OVER (ORDER BY widgetName,WidgetType) RowID
FROM #widget
)t1
JOIN CTE_OE t2
ON t1.RowID=t2.Rowid
),
CTE_2(OutputColumn,RowID)
AS
(
Select t1.OutputColumn
,t2.EvenNum
From
(
SELECT 'Type'+ ' = ' + q1.WidgetType + ', Avg = ' + q1.categoryAvg As OutputColumn
,ROW_NUMBER() OVER (ORDER BY q1.WidgetType) AS RowID
FROM #categoryAvg q1
JOIN CTE_1 q2
on q1.WidgetType=q2.WidgetType
)t1
JOIN CTE_OE t2
ON t1.RowID=t2.Rowid
)
Select OutputColumn
From
(
Select OutputColumn,RowID from CTE_1
union all
select OutputColumn,RowID from CTE_2
)qry
order by RowID
OPTION (MAXRECURSION 0);
I don't know C# personally, so I don't know how hard/easy this would be to do within the application, but just as a side thought, one way you might be able to approach it within the SQL query without having to make the two separate queries and alternate display and all... an option might be to just do a join and display results side by side. What I mean is you could do something along the lines of:
SELECT Widget.Name, Widget.Category, Widget.Speed, Category.Speed AS AvgSpeed
FROM Widget
INNER JOIN Category
ON Widget.Category=Category.Name;
Then you would end up having a table something along the lines of
Name Category Speed AvgSpeed
W1 Sample 1ms 2ms

Counting the rows of a column where the value of a different column is 1

I am using a select count distinct to count the number of records in a column. However, I only want to count the records where the value of a different column is 1.
So my table looks a bit like this:
Name------Type
abc---------1
def----------2
ghi----------2
jkl-----------1
mno--------1
and I want the query only to count abc, jkl and mno and thus return '3'.
I wasn't able to do this with the CASE function, because this only seems to work with conditions in the same column.
EDIT: Sorry, I should have added, I want to make a query that counts both types.
So the result should look more like:
1---3
2---2
SELECT COUNT(*)
FROM dbo.[table name]
WHERE [type] = 1;
If you want to return the counts by type:
SELECT [type], COUNT(*)
FROM dbo.[table name]
GROUP BY [type]
ORDER BY [type];
You should avoid using keywords like type as column names - you can avoid a lot of square brackets if you use a more specific, non-reserved word.
I think you'll want (assuming that you wouldn't want to count ('abc',1) twice if it is in your table twice):
select count(distinct name)
from mytable
where type = 1
EDIT: for getting all types
select type, count(distinct name)
from mytable
group by type
order by type
select count(1) from tbl where type = 1
;WITH MyTable (Name, [Type]) AS
(
SELECT 'abc', 1
UNION
SELECT 'def', 2
UNION
SELECT 'ghi', 2
UNION
SELECT 'jkl', 1
UNION
SELECT 'mno', 1
)
SELECT COUNT( DISTINCT Name)
FROM MyTable
WHERE [Type] = 1

SQL - order by list order

I have the following query that returns rows based on a comma seperated list
Select * from Table where RecordID in (22,15,105,1,65,32)
I would like the results of this query to return to in the order of the ID's in the list. Is that possible with SQL?
Thanks in advance
select * from Table
where RecordID in (22,15,105,1,65,32)
order by (
case RecordID
when 22 then 1
when 15 then 2
when 105 then 3
when 1 then 4
when 65 then 5
when 32 then 6 end)
If you need the output to appear in a particular order, then you need to specify that order, using something the server can sort. Not knowing which engine you're working against, the general scheme would be to create a temp table or use rowset constructors to pair each record ID with its desired sort order.
E.g. (SQL Server)
declare #T table (RecordID int,Position int)
insert into #T (RecordID,Position)
select 22,1 union all
select 15,2 union all
select 105,3 union all
select 1,4 union all
select 65,5 union all
select 32,6
select * from Table t inner join #T t2 on t.RecordID = t2.RecordID order by t2.Position
I'd to the ordering in the client, but if you really want to do it in SQL, do it like this:
declare #T table (id int identity(1,1), RecordID int)
insert into #T (RecordID)
values (22), (15), (105), (1), (65), (32)
select * from
[table] t
inner join #t s on t.id=s.recordid
where t.id in (22, 15, 105, 1, 65, 32)
order by s.id
(works in SQL Server 2008)
Yes. You add the ORDER BY recordedid clause at the end.
The last time I had to do this I ended up doing a union all and generating a select statement for each id, i.e.
select * from Table where RecordID = 22
union all
select * from table where recordid = 15
etc.
It was a pain but it worked.
Use ORDER BY against the RecordID
Select * from Table where RecordID in (22,15,105,1,65,32) ORDER BY RecordID