SQL - Insert NULL entry with Union then order by results - sql

Im trying to order a list of results by their description (not id) but i also need to insert another result with a null Id and description of 'ALL'.
To do this I use UNION SELECT NULL, 'ALL'
It should be a pretty simple query but i cant figure out how to insert 'ALL' before the query orders the actual result set.
Here is what I have so far:
SELECT *
FROM [dbo].[HouseType]
WHERE [TypeId] = COALESCE(#TypeId, [TypeId])
UNION SELECT NULL, 'ALL'
ORDER BY [TypeDesc]
Ive also tried calling UNION SELECT before the results are ordered but it doesnt look SQL allows this.
UNION SELECT NULL, 'ALL'
SELECT * FROM
(
SELECT *
FROM [dbo].[HouseType]
WHERE [TypeId] = COALESCE(#TypeId, [TypeId])
ORDER BY [TypeDesc]
)types
Basically I want to see the following results (ordered):
ALL
Bungalow
Detached
Semi-Detached
Terrace

Try using another column:
SELECT t.ID, t.description, 2 AS o
FROM [dbo].[HouseType] AS t
WHERE [TypeId] = COALESCE(#TypeId, [TypeId])
UNION ALL
SELECT NULL, 'ALL', 1 AS o
ORDER BY o, [TypeDesc]
This way ALL will always precede the results of your original query.
Note: As already noted in a comment there must be a match between the number and type of fields of the subqueries used in the UNION operation.
Note 2: As noted in the other comment by #A ツ using UNION ALL is always preferable over UNION, so use this instead when you have no worries about duplicate values.

Try it in a subquery
SELECT *
FROM(
SELECT *
FROM [dbo].[HouseType]
WHERE [TypeId] = COALESCE(#TypeId, [TypeId])
UNION
SELECT NULL, 'ALL')
ORDER BY [TypeDesc]

DECLARE #HouseType TABLE (HouseType VARCHAR(30))
INSERT INTO #HouseType
SELECT HouseType
FROM [dbo].[HouseType]
WHERE [TypeId] = COALESCE(#TypeId, [TypeId])
ORDER BY [TypeDesc]
INSERT INTO #HouseType
SELECT 'ALL'
SELECT HouseType FROM #HouseType ORDER BY HouseType

I think you are looking for conditional sorting:
SELECT *
FROM [dbo].[HouseType]
WHERE [TypeId] = COALESCE(#TypeId, [TypeId])
UNION ALL
SELECT NULL, 'ALL'
ORDER BY CASE WHEN [TypeDesc] = 'ALL' THEN 0 ELSE 1 END, [TypeDesc]
btw, I would suggest agains the use of * and explicitly specify the column names in the select list.
This is always best practice, espcially when using UNION - this query will raise an error if you ever add (or remove) a column from the HouseType table.

Assigns a Row to each TypeDesc using ROW_NUMBER function (+1 to go after the 'ALL') sorted by TypeDesc:
select 1 as [Row], 'All' as [TypeDesc]
union
SELECT ROW_NUMBER() OVER (ORDER BY TypeDesc) + 1 AS [Row], [TypeDesc]
FROM [dbo].[HouseType]
WHERE [TypeId] = COALESCE(#TypeId, [TypeId])
ORDER BY [Row]

Related

How to ROWCOUNT_BIG() value with union all

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

How do I exclude null duplicates without excluding valid nulls - SQL Server

I'm using a SQL Server and am trying to pull certain data. However, some rows pop up with duplicate order #s, where one line # is null while the other has a correct value.
The tricky thing is that there also are other line #s that are null, and if I were to do a filter that line_id is not null then I would exclude all the valid order #s with null values. Would I use a case statement? A subquery? I'm at a loss.
Here's an abridged version of my code and what I mean:
select
order_number
line_number
from table_1
With NOT EXISTS:
select t.*
from tablename t
where t.line_number is not null
or not exists (
select 1 from tablename
where order_number = t.order_number and line_number is not null
)
or with ROW_NUMBER() window function:
select t.order_number, t.line_number
from (
select *,
row_number() over (partition by order_number order by case when order_number is not null then 1 else 2 end) rn
from tablename
) t
where t.rn = 1

SQL Having count logic

i need help on HAVING COUNT , i have a result set of data below:
CREATE TABLE #tmpTest1 (Code VARCHAR(50), Name VARCHAR(100))
INSERT INTO [#tmpTest1]
(
[Code],
[Name]
)
SELECT '160215-039','ROBIN'
UNION ALL SELECT '160215-039','ROBIN'
UNION ALL SELECT '160215-046','SENGAROB'
UNION ALL SELECT '160215-046','BABYPANGET'
UNION ALL SELECT '160215-045','JONG'
UNION ALL SELECT '160215-045','JAPZ'
UNION ALL SELECT '160215-044','AGNES'
UNION ALL SELECT '160215-044','AGNES'
UNION ALL SELECT '160215-041','BABYTOT'
UNION ALL SELECT '160215-041','BABYTOT'
UNION ALL SELECT '160215-041','BABYTOT'
i want to show only the rows that have the same code but different name , so in this case my expected result is below since those are have the same code but different name:
160215-045 JAPZ
160215-045 JONG
160215-046 BABYPANGET
160215-046 SENGAROB
but when i try to group the two columns then use the having count, below is my query:
SELECT [Code], [Name] FROM [#tmpTest1]
GROUP BY [Code], [Name] HAVING COUNT([Code]) > 1
It gives me wrong result below which have the rows that have the same code and name, it is the opposite of what i want.
160215-044 AGNES
160215-041 BABYTOT
160215-039 ROBIN
How can i get my expected output ?
Thanks in advance, any help would much appreciated.
I believe this query will give you the result you want, although your original question is a bit unclear.
SELECT t1.[Code], t1.[Name]
FROM [#tmpTest1] t1
INNER JOIN
(
SELECT [Code]
FROM [#tmpTest1]
GROUP BY [Code]
HAVING COUNT(DISTINCT [Name]) > 1
) t2
ON t1.[Code] = t2.[Code]
Follow the link below for a running demo:
SQLFiddle
If you want rows with the same code and name, then use window functions:
select t.*
from (select t.*, count(*) over (partition by code, name) as cnt
from #temptest1 t
) t
where cnt >= 2;
From your comment
if there is 1 different name for the codes , i want to show those
records for me to know that there is one differs to others..
This sounds like an exists query because you want to check if another row with the same code but different name exists.
select * from [#tmpTest1] t1
where exists (
select 1 from [#tmpTest] t2
where t2.code = t1.code
and t2.name <> t1.name
)

SQL add ALL to select statement

I have a select statement which displays a list of companies.
SELECT distinct [Company]
FROM [Records]
How can I add the entry "ALL" as the first item on the returned list?
Use union all and order by:
select company
from ((select distinct company, 1 as ordering from records)
union all
(select 'ALL', 0)
) t
order by ordering;
In practice, the following would seem to work:
select 'ALL' as company
union all
select distinct company from records;
However, SQL Server does not guarantee that these are executed in order. In practice, I have never found a case where this statement would not put ALL first, but it is not guaranteed as far as I know.
You can use UNION ALL and add order:
SELECT [Company] FROM
(SELECT 'All' as [Company], 0 as RecordOrder
UNION ALL
SELECT distinct [Company], 1 as RecordOrder
FROM [Records]) X
ORDER BY RecordOrder
try with union all
SELECT 'ALL'
UNION ALL
SELECT distinct [Company]
FROM [Records]
SELECT 'ALL'
UNION ALL
SELECT distinct [Company]
FROM [Records]

Unioned queries with subqueries disobeys order by clauses

I have a query:
select * from (select top 100 percent ... from [table]
where [field1] is not null
order by [field1]) a
union all
select * from (select top 100 percent ... from [table]
where [field1] is null
order by [field2]) b
The subqueries are ordering their results correctly. I want the exact results of the first subquery, THEN the exact results of the second subquery. However, I'm actually getting the concatenated results ordered in some odd way that I can't even discern a pattern from. I have [field2] values scattered about the result set apparently at random.
How can I get the first query results on top, and the second query results on bottom?
Edit: To clarify, I want the top query ordered by its own conditions, and then I want the bottom query ordered by its own conditions.
I am not sure, whether or not UNION ALL is meant to preserve the order of rows.
You can force the order you want by using the following statement:
select [field1] from
(
select * from
(select 1 as query_number, [field1], [field1] as [order_field] from [table]
where [field1] is not null) a
union all
select * from
(select 2 as query_number, [field1], [field2] as [order_field] from [table]
where [field1] is null) b
)
order by query_number, [order_field];
select * from (select top 100 percent ..., 1 AS q from [table]
where [field1] is not null
order by [field1]) a
union all
select * from (select top 100 percent ..., 2 AS q from [table]
where [field1] is null
order by [field2]) b
order by q
, CASE q
WHEN 1 THEN fieldX
WHEN 2 THEN fieldY
END