Override alphabetical default ORDER BY with a UNION of 2+ tables? - sql

Really quick question... I have 4 tables that are UNION-ed together like so:
SELECT * FROM table1
UNION
SELECT * FROM table2
UNION
SELECT * FROM table3
UNION
SELECT * FROM table4
Without specifying an ORDER BY, the query orders by the first column in ascending alphabetical order (which in my case happens to be a varchar type). I don't want ORDER BY [Column1] DESC either.
I simply want to order the results in the same order as the tables themselves are UNION-ed. 1, 2, 3, 4.
Is there a simply way to do this?
Thanks!!

One way
SELECT *,1 as SortOrder FROM table1
UNION
SELECT *,2 FROM table2
UNION
SELECT *,3 FROM table3
UNION
SELECT *,4 FROM table4
order by SortOrder
what happens is that you are using UNION, sql server then makes the result set distinct, in order to do that it needs to sort the tables
Does UNION ALL make a difference?

We had a similar issue. We have a union query with 32 subsets. We use it to populate a spreadsheet that is then used to build a PowerPoint presentation. The first field in each query is a text field that is a description of the data point. The spreadsheet is expecting the data to be in a specific order.
We made a slight change to one of the fields:
Concat('Annual incidence rate- ', Year(start_date))
This caused SQL to sort the unions in alphabetical order! I suspect that if you ordered your query as #SQLMenace indicated, but with a slight modification, it would work too.
SELECT '1', * FROM table1
UNION
SELECT '2', * FROM table2
UNION
SELECT '3', * FROM table3
UNION
SELECT '4', * FROM table4
This might alleviate the outer query wrapper. It might work without the quotes, too.

Related

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

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.

Using Union with Insert to add one row

I have a query which is made up of two select statements with a union in the middle.
This works for what I need it for.
However, there is one value missing which I want to manually enter.
What I'm looking to is:
select * from tab1
union
select * from tab2
union
insert values('John',cast('2013-01-01' as date), 'Jim', 130)
Unfortunately this is not working. Can someone suggest how I do this please?
I'm using Teradata.
You need to keep selecting:
select * from tab1
union
select * from tab2
union
select 'John', cast('2013-01-01' as date), 'Jim', 130 from dual
The name dual is used in Oracle for a table with one row (and one column). Depending on the DBMS you use, you may be able to omit that final FROM altogether (and you may be able to do this in Oracle too):
select * from tab1
union
select * from tab2
union
select 'John', cast('2013-01-01' as date), 'Jim', 130
or you may have to choose from a system catalog table and ensure you get one row returned (FROM systables WHERE tabid = 1 was the classic mechanism in Informix, though you could also use 'sysmaster':sysdual instead of dual, etc, too), or you can select from any other table with a query that is guaranteed one row. There are probably ways to do it using a VALUES clause too.
Note the change from double quotes to single quotes. In strict standard SQL, double quotes enclose a delimited identifier, but single quotes surround strings.
From your question I' guessing you just want to SELECT that row, not INSERT it (into the database):
select * from tab1
union
select * from tab2
union
select "John", cast('2013-01-01' as date), "Jim", 130
You just want to SELECT the data, not INSERT it.
Not very familiar with TeraData, perhaps you need a FROM in which case limiting to 1 record would also make sense:
select * from tab1
union
select * from tab2
union
SELECT 'John',cast('2013-01-01' as date), 'Jim', '130' FROM dbc.columns 1
I am affraid the union must reference a table and if you need to add the data that does not exist in your database, try this:
select * from tab1
union
select * from tab2
union
select * from (SELECT 'John' as col1 ,cast('2013-01-01' as date) as col2, 'Jim' as col3, '130' as col4) dummy
You will, of course, have to change the name of the columns to fit those from your db (i.e. dont use col1, col2 etc.).
Good luck!

UNION ALL query: "Too Many Fields Defined"

I'm trying to get a UNION of 3 tables, each of which have 97 fields. I've tried the following:
select * from table1
union all
select * from table2
union all
select * from table3
This gives me an error message:
Too many fields defined.
I also tried explicitly selecting all the field names from the first table (ellipses added for brevity):
select [field1],[field2]...[field97] from table1
union all
select * from table2
union all
select * from table3
It works fine when I only UNION two tables like this:
select * from table1
union all
select * from table2
I shouldn't end up with more than 97 fields as a result of this query; the two-table UNION only has 97. So why am I getting Too many fields with 3 tables?
EDIT: As RichardTheKiwi notes below, Access is summing up the field count of each SELECT query in the UNION chain, which means that my 3 tables exceed the 255 field maximum. So instead, I need to write the query like this:
select * from table1
union all
select * from
(select * from table2
union all
select * from table3)
which works fine.
It appears that the number of fields being tracked (limit 255) is counted against ALL parts of the UNION ALL. So 3 x 97 = 291, which is in excess. You could probably create a query as a UNION all of 2 parts, then another query with that and the 3rd part.
I had two tables with 173 fields each (2 x 173 > 255!). So I had to resort to splitting the tables in half (keeping the primary key in both), before using the UNION statement and reassembling the resulting output tables using a JOIN.
select u1.*, u2.*
from (
select [field1_PKID],[field2],...,[field110]
from table1
union all
select [field1_PKID],[field2],...,[field110]
from table2
) as u1
inner join (
select [field1_PKID],[field111],...,[field173]
from table1
union all
select [field1_PKID],[field111],...,[field173]
from table2
) as u2
on [u1].[field1_PKID] = [u2].[field2_PKID]
Perhaps if your 3 tables have duplicate records you can go with UNION instead of UNION ALL which may reduce the number of fields to be tracked. Because UNION will always serve the business purpose which removes duplicates. In that case your query will be like following,
select * from table1
union
select * from table2
union
select * from table3;

Combining several query results into one table, how is the results order determined?

I am retuning table results for different queries but each table will be in the same format and will all be in one final table. If I want the results for query 1 to be listed first and query2 second etc, what is the easiest way to do it?
Does UNION append the table or are is the combination random?
The SQL standard does not guarantee an order unless explicitly called for in an order by clause. In practice, this usually comes back chronologically, but I would not rely on it if the order is important.
Across a union you can control the order like this...
select
this,
that
from
(
select
this,
that
from
table1
union
select
this,
that
from
table2
)
order by
that,
this;
UNION appends the second query to the first query, so you have all the first rows first.
You can use:
SELECT Col1, Col2,...
FROM (
SELECT Col1, Col2,..., 1 AS intUnionOrder
FROM ...
) AS T1
UNION ALL (
SELECT Col1, Col2,..., 2 AS intUnionOrder
FROM ...
) AS T2
ORDER BY intUnionOrder, ...