Order two parts of a union independently of one another - sql

Is it possible to do something like this:
select name from table1 order by name
union
select name from table2 order by name
I know I can do this:
select name from table1
union
select name from table2 order by name
However, I want the names from table1 to appear first. I have spent the last hour Googling this and I have go nowhere. For example, I have looked here: How to order by with union in SQL?

The query needs to be a bit more complicated:
select name
from ((select distinct name, 1 as is_1 from table1)
union
(select distinct name, 0 from table2)
) n
group by name
order by max(is_1), name;
This uses select distinct in the subqueries because that can take advantage of an index on name.

Add a "sort" field and put the union inside a subquery so you can sort after the union.
untested
select a.name
from (
select name, 1 sort
from table1
union all
select name, 2 sort
from table2
) a
order by a.sort, a.name
I changed it to union all to make it clear this approach won't do a union. You could also select the sort column if you want to see it. If you don't want duplicate names, then this approach won't work.

You need another column to sort on. UNION does not allow the individual queries to have an ORDER BY clause.
Adding in a column to sort on before name allows for it to sort the individual result sets. See my example below:
CREATE TABLE #Table1 (Name VARCHAR(50))
CREATE TABLE #Table2 (Name VARCHAR(50))
INSERT INTO #Table1 VALUES ('Bart'), ('Lisa'), ('Maggie')
INSERT INTO #Table2 VALUES ('Chris'), ('Meg'), ('Stewie')
SELECT Name, 0 AS Sort FROM #Table1
UNION
SELECT Name, 1 AS Sort FROM #Table2
ORDER BY Sort, Name

Related

SQL check or uniqueness in one column in multipe tables

I have a 'unique' column, 'GID_New' that is in multiple tables. Is there a way to check if it's unique across all the tables in the QGIS project in SQL?
Can it be done in one SQL search without merging the tables into one and then running something like
SELECT A.GID_New, count(*), A.TableName
FROM "Water_Merged" as A
Group by A.GID_New
And then checking for a count >1
I would like to know which table the non-unique GID_New's are from as well.
The data is in a geopackage in QGIS so the code needs to work in QGIS SQL implementation.
You can use union all:
select gid_new, count(*) no_matches
from (
select gid_new from table1
union all select gid_new from table2
union all select gid_new from table3
) t
group by gid
having count(*) > 1
If you want to know in which table duplicates exists, then one option is string concatenation. Assuming that your database uses string_agg(), that would look like:
select gid_new, count(*) no_matches, string_agg(which, ',') which_tables
from (
select 'table1' which, gid_new from table1
union all select 'table2', gid_new from table2
union all select 'table3', gid_new from table3
) t
group by gid
having count(*) > 1

Union of multiple queries using the count function

I'm working on learning more about how the UNION function works in SQL Server.
I've got a query that is directed at a single table:
SELECT Category, COUNT(*) AS Number
FROM Table1
GROUP BY Category;
This returns the number of entries for each distinct line in the Category column.
I have multiple tables that are organized by this Category column and I'd like to be able to have the results for every table returned by one query.
It seems like UNION will accomplish what I want it to do but the way I've tried implementing the query doesn't work with COUNT(*).
SELECT *
FROM (SELECT Table1.Category
Table1.COUNT(*) AS Number
FROM dbo.Table1
UNION
SELECT Table2.Category
Table2.COUNT(*) AS Number
FROM dbo.Table2) AS a
GROUP BY a.Category
I'm sure there's an obvious reason why this doesn't work but can anyone point out what that is and how I could accomplish what I'm trying to do?
You cannot write a common Group by clause for two different select's. You need to use Group by clause for each select
SELECT TABLE1.Category, --missing comma here
COUNT(*) as Number -- Remove TABLE1. alias name
FROM dbo.TABLE1
GROUP BY Category
UNION ALL --UNION
SELECT TABLE2.Category, --missing comma here
COUNT(*) as Number -- Remove TABLE1. alias name
FROM dbo.TABLE2
GROUP BY Category
If you really want to remove duplicates in result then change UNION ALL to UNION
COUNT as any associated aggregation function has to have GROUP BY specified. You have to use group by for each sub query separately:
SELECT * FROM (
SELECT TABLE1.Category,
COUNT(*) as Number
FROM dbo.TABLE1
GROUP BY TABLE1.Category
UNION ALL
SELECT TABLE2.Category,
COUNT(*) as Number
FROM dbo.TABLE2
GROUP BY TABLE2.Category
) as a
It is better to use UNION ALL vs UNION - UNION eliminates duplicates from result sets, since - let say - you want to merge both results as they are it is safer to use UNION ALL

Getting distinct list of ints from 2 distinct int lists

I have 2 separate queries that are just basic selects, both returning a single distinct column of ints. I need to then combined these 2 lists of ints together to produce a final single distinct list of ints.
Is there any faster way to do this than the following?
SELECT DISTINCT ID
FROM dbo.Test
UNION
SELECT DISTINCT ID
FROM dbo.Test2
If you don't have duplicates within each table, then the following is probably faster:
select id
from dbo.test
union all
select id
from dbo.test1 t1
where not exists (select 1 from dbo.test t where t.id = t1.id);
For this, you want an index on test(id).
Even with duplicates, the following is likely to be faster:
select distinct id
from dbo.test
union all
select distinct id
from dbo.test1 t1
where not exists (select 1 from dbo.test t where t.id = t1.id);
This requires indexes for both test(id) and test1(id). The idea is that the indexes are scanned to return the id.
I think that the fastest approach in your case is to remove the two DISTINCT since UNION will remove all duplicates overall anyway:
SELECT ID
FROM dbo.Test
UNION
SELECT ID
FROM dbo.Test2
Note that the two DISTINCTs don't ensure uniqueness across both sequences anyway, that's what the UNION does. If you don't need/want unique elements use UNION ALL.

order by only one dataset of a union in a tsql union of datasets

I have the following problem.
Let TableA(Id int, Name nvarchar(200)) and TableB(Id int, Name nvarchar(200)).
If we run the following query:
SELECT *
FROM
(SELECT *
FROM TableA)
UNION
(SELECT *
FROM TableB)
we get the union of the two datasets.
My Problem is that I want the results of the second dataset to be the ordered by the Name column.
The reason why I need this, is the fact that TableA is a temporary table in my query, that always will hold one record, and this record I want to be the first in the resulting dataset from the union of the two datasets. Also, I want the multiple records of the TableB to be ordered by the Name column.
Unfortunately, when I try to execute the following query
SELECT *
FROM
(SELECT *
FROM TableA)
UNION
(SELECT *
FROM TableB
ORDER BY Name)
I get an ambiguous error message, that informs me that I have an incorrect syntax near the keyword order.
Thanks in advance for any help.
try this:
select id
, name
from
(select 1 as ordercol
, a.id
, a.name
from tableA
union
select 2 as ordercol
, b.id
, b.name
from tableB) i
order by ordercol, name
the error message resulted in you trying to union two subselects. you can put union between two selects that will then be put into a subselect. there is always a select after a union (or union all). i would also suggest you use a union all, that saves time because sql-server will otherwise try and remove records that are in both selects (which in this case is impossible due to the ordercol-column)
i have included a second order-by column that will order the first select before the second. if you order by that first and then by name, you should get the desired result.

Get the most recently used date from two different tables with two different named columns

I've two tables say table 1 and table 2,
table 1 has column names as sno and useddate
table 2 has column names as sno and recentlyuseddate
I want to compare these two columns useddate and recentlyusedate and get the most recently used date.
These tables may have many entries but I need only ONE ENTRY (mostrecent) date after comparing these tables.
SELECT MAX(useddate) AS mostrecent
FROM
(SELECT useddate FROM Table1
UNION ALL
SELECT recentlyuseddate AS useddate FROM Table2) TheUnion
You can use unions for this
SELECT MAX(col)
FROM (SELECT col FROM TABLE_1
UNION ALL
SELECT col FROM TABLE_2)
If you have an index on the two dates in the two tables, I would go for:
select top 1 sno, useddate, which
from ((select top 1 sno, useddate, 'table1' as which from table1 order by useddate desc) union all
(select top 1 sno, recentlyuseddate , 'table2' as which from table2 order by recentlyuseddate desc)
)
order by useddate desc;
This version also tells you which table the date came from.