Does table1 UNION ALL table2 guarantee output order table1, table2? - sql

SELECT a FROM b
UNION ALL
SELECT a FROM c
UNION ALL
SELECT a FROM d
Does UNION ALL guarantee to print out records from tables b, c, d in that order? I.e., no records from c before any from b. This question is not for a specific DBMS.

No order by, no order guarantee whatsoever - that's for every database.
And for standard SQL, an ORDER BY is applied to the results from all the unioned queries.

To be sure in order use
Select 1 as TableNo,* from a
union all
select 2 as TableNo,* from b
union all
select 3 as TableNO,* from c
order by TableNo, [desired column]

Related

Looking for performance improvements in the SQL

Scenario:
There are 2 columns in the table with data as given in the sample below.
It is possible that the table has multiple rows for the same value of 'a' column.
In the example, Considering the 'a' column, There are three rows for '1' and one row for '2'.
Sample table 't1':
|a|b |
|1|1.1|
|1|1.2|
|1|2.2|
|2|3.1|
Requirement is to get following output:
Expected Query output:
|a|b |
|1|1.2|
|2|3.1|
Requirement:
Get the row if there is only one row for a given value for column 'a'.
If there are multiple rows for the same value for column 'a' and for all rows, FLOOR(b) == a, then get MIN(a) and MAX(b)
If there are multiple rows for column 'a' and for all rows, there is 1 row of column 'b' for which
FLOOR(b) > a, then ignore that row. from the remaining rows, get MIN(a) and MAX(b)
Query I used:
select distinct min(a) over(partition by table1.a) as a,
min(b) over(partition by table1.a) as b
from (
SELECT distinct Min(table2.a) OVER (PARTITION BY table2.a) AS a,
Max(table2.b) OVER (PARTITION BY table2.a) AS b
FROM t1 table2
union
SELECT distinct Min(table3.a) OVER (PARTITION BY table3.a) AS a,
Max(table3.b) OVER (PARTITION BY table3.a) AS b
FROM t1 table3
where table3.a = FLOOR(table3.b)
) table1;
This query is working and I am getting the desired output. Looking for inputs to improve by removing union and extra select from the above script.
Note: t1 is not a table but it's a procedure call in my case and there are additional columns that it returns. It would help if the extra call to the procedure can be avoided.
This is how I would get the data you need.
select t1.a, max(t1.b)
from (select a, b, count(1) over(partition by t1.a) cnt from t1) t1
where t1.a = floor(t1.b) or cnt = 1
group by t1.a ,cnt;
It has only one procedure call so it might run significantly faster
And please note that "union" clause not only appends two data sets, but removes duplicates as well. Removing duplicates causes additional checks between data sets and therefore is leading to performance issues.
It is in most cases better to use "union all" which doesn't check for duplicates

Gridgain SQL query not working with union all and order by

SELECT a, b
FROM "table1".table1 table1
ORDER BY a DESC
UNION ALL
SELECT a, b
FROM "table1".table1 table1
ORDER BY a ASC
This query does not work. Individually, union all works and order by works, but does not work when together. Can someone please help?
Answered this question on GridGain forum
This should work:
SELECT a, b, b, NULL FROM "table1".table1 table1
UNION ALL
SELECT a, b, NULL, b FROM "table1".table1 table1
ORDER BY 3 DESC, 4 ASC
You can sort in an outer query:
select a, b
from (
select a, b, 0 x from table1
union all select a, b, 1 from table1
) t
order by
x,
case when x = 0 then a end desc,
case when x = 1 then a end
Individual query won't support order by if we are using UNION.
Try to remove order by in separate query and after union they to perform order by then it will work.

Keep Track of already summed tuples sql

If we have a table with values for a and b, is there a way to only add up the b's if its not a duplicate a? For example
a b
1 2
2 3
2 3
so we would get only 5 (instead of 8)
A sort of
select sum(b if unique a),
from table
where ...
The following query selects the lowest value of b for each group a
select min(b) min_b
from mytable
group by a
You can then sum those values by selecting the sum from a derived table
select sum(min_b) from (
select min(b) min_b
from mytable
group by a
) t
http://sqlfiddle.com/#!9/d82c5/1
You haven't specified your RDBMS, but if you are using a database which supporting window functions like SQL Server, you can query the unique rows first by using WITH clause and ROW_NUMBER() function and then get the SUM out of that.
;WITH C AS(
SELECT a, b,
ROW_NUMBER() OVER (PARTITION BY a ORDER BY a) AS Rn
FROM Table1
)
SELECT SUM(b) FROM C
WHERE Rn = 1
SQL Fiddle

Which select is faster in Sqlite?

a is a table index, b is a normal column.
select a,b from ( select a,b from table where a in (*listA*) ) where b in (*listB*)
or
select a,b from table where (a=listA[0] and b=listB[0]) or (a=listA[1] and b=listB[1])...
I am using pseudocode to represent a list declaration.
The first query is wrong because it never looks at the combinations of a and b.
To use a temp table, you have to join with it:
SELECT a, b
FROM MyTable
JOIN (SELECT 1 AS a, 2 AS b UNION ALL
SELECT 3, 4 UNION ALL
SELECT 5, 6 ...)
USING (a, b)
Which version is better optimized depends on too many factors; the only way to find out is to measure with representative data.

How to use group by with union in T-SQL

How can I using group by with union in T-SQL? I want to group by the first column of a result of union, I wrote the following SQL but it doesn't work. I just don't know how to reference the specified column (in this case is 1) of the union result.
SELECT *
FROM ( SELECT a.id ,
a.time
FROM dbo.a
UNION
SELECT b.id ,
b.time
FROM dbo.b
)
GROUP BY 1
You need to alias the subquery. Thus, your statement should be:
Select Z.id
From (
Select id, time
From dbo.tablea
Union All
Select id, time
From dbo.tableb
) As Z
Group By Z.id
GROUP BY 1
I've never known GROUP BY to support using ordinals, only ORDER BY. Either way, only MySQL supports GROUP BY's not including all columns without aggregate functions performed on them. Ordinals aren't recommended practice either because if they're based on the order of the SELECT - if that changes, so does your ORDER BY (or GROUP BY if supported).
There's no need to run GROUP BY on the contents when you're using UNION - UNION ensures that duplicates are removed; UNION ALL is faster because it doesn't - and in that case you would need the GROUP BY...
Your query only needs to be:
SELECT a.id,
a.time
FROM dbo.TABLE_A a
UNION
SELECT b.id,
b.time
FROM dbo.TABLE_B b
Identifying the column is easy:
SELECT *
FROM ( SELECT id,
time
FROM dbo.a
UNION
SELECT id,
time
FROM dbo.b
)
GROUP BY id
But it doesn't solve the main problem of this query: what's to be done with the second column values upon grouping by the first? Since (peculiarly!) you're using UNION rather than UNION ALL, you won't have entirely duplicated rows between the two subtables in the union, but you may still very well have several values of time for one value of the id, and you give no hint of what you want to do - min, max, avg, sum, or what?! The SQL engine should give an error because of that (though some such as mysql just pick a random-ish value out of the several, I believe sql-server is better than that).
So, for example, change the first line to SELECT id, MAX(time) or the like!
with UnionTable as
(
SELECT a.id, a.time FROM dbo.a
UNION
SELECT b.id, b.time FROM dbo.b
) SELECT id FROM UnionTable GROUP BY id