Google BigQuery UNION ALL Not Working As Expected - google-bigquery

This works just fine:
SELECT
DISTINCT query
FROM
(SELECT * FROM (
(SELECT query, impressions FROM a_temp.sqpr1)
UNION ALL
(SELECT query, impressions FROM a_temp.sqpr2)
)
)
This gives an error:
SELECT
DISTINCT query
FROM
(SELECT query, impressions FROM a_temp.sqpr1)
UNION ALL
(SELECT query, impressions FROM a_temp.sqpr2)
Specifically, the error is: Queries in UNION ALL have mismatched column count; query 1 has 1 column, query 2 has 2 columns at [6:2]
Both queries clearly have 2 columns.

BigQuery is parsing your query as:
SELECT
DISTINCT query
FROM
(SELECT query, impressions FROM a_temp.sqpr1)
UNION ALL
(SELECT query, impressions FROM a_temp.sqpr2)
not as:
SELECT
DISTINCT query
FROM
(SELECT query, impressions FROM a_temp.sqpr1)
UNION ALL
(SELECT query, impressions FROM a_temp.sqpr2)
The parser is seeing (SELECT DISTINCT query FROM X) UNION ALL (Y), not SELECT DISTINCT query FROM (X UNION ALL Y), which is why it's complaining about mismatched column counts: the column counts are mismatched!
The first query with the explicit parenthetical grouping works because it forces the parser to see the query in the latter form, as opposed to the former, which has column counts that match.

Related

oracle count query with union

I have a query with union all functionality each giving me count(*) return from respective queries and another count query like below. I want an outer query that gives the total.
1st query
select count(*) from a
union all
select count(*) from b;
Sample result for 1st query:
COUNT
10
40
2nd query
select count(*) from xy;
Sample result for 2nd query:
COUNT
20
I want output like this in 2 rows:
TABLES
COUNT
xy
20
ab
50
something like above. How can I achieve this in oracle? please suggest the best way to do this.
I wrote a select and union all but not sure how to proceed further.
One option is to sum counts returned by the 1st query and then union it with the 2nd; also, add constants which show the source:
select 'ab' what, (select count(*) from a) + (select count(*) from b) cnt from dual
union all
select 'xy', count(*) from xy;
You can use:
SELECT 'ab' AS type,
COUNT(*) AS total
FROM ( SELECT 1 FROM a UNION ALL
SELECT 1 from b );
UNION ALL
SELECT 'xy', COUNT(*)
FROM xy;
You can sum counts from your three unioned Select statements and group the result by combination of sources:
WITH
a AS
( Select LEVEL "A_ID", 'some column a' "COL_A" From Dual Connect By LEVEL <= 30 ),
b AS
( Select LEVEL "B_ID", 'some column b' "COL_B" From Dual Connect By LEVEL <= 20 ),
xy AS
( Select LEVEL "XY_ID", 'some column xy' "COL_XY" From Dual Connect By LEVEL <= 20 )
with above sample data it is like here:
SELECT
CASE WHEN SOURCE IN('a', 'b') THEN 'ab' ELSE SOURCE END "SOURCE",
Sum(CNT) "CNT"
FROM
( Select 'a' "SOURCE", Count(*) "CNT" From a Union All
Select 'b', Count(*) From b Union All
Select 'xy', Count(*) From xy
)
GROUP BY
CASE WHEN SOURCE IN('a', 'b') THEN 'ab' ELSE SOURCE END
--
-- R e s u l t :
-- SOURCE CNT
-- ------ ----------
-- ab 50
-- xy 20
Assuming that your real queries can be a lot more complex, I take it as a given that we shall not try to change them and somehow merge or split them.
Your first query returns two rows. You want to get their sum, so you must aggregate the result and use SUM.
Below query uses CTEs (subqueries in the WITH clause) for your two queries, and then a query that gets this sum. It then uses these CTEs for the final UNION ALL query.
with query1 (cnt) as (select count(*) from a union all select count(*) from b)
, query2 (cnt) as (select count(*) from xy)
, sumquery1 (total) as (select sum(cnt) from query1)
select 'ab' as tables, total from sumquery1
union all
select 'xy' as tables, cnt from query2
order by tables desc;

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.

Oracle Query fetching table name alongwith column name

select trx_id,refernce number from
(select * from abcd_1_txt union
select * from abcd_2_txt union
select * from abcd_3_txt union
select * from abcd_4_txt)
where trx_id in (123,321,1234)
In the query all the tables are of same format, same column names and same number of columns.
After running this query, surely i will get some data.
My question --- is there any way to know from which of these tables, i am getting the output.
Try to add a column with number of query as below
select qrynum, trx_id,refernce number from
(select 1 as qrynum,* from abcd_1_txt union
select 2,* from abcd_2_txt union
select 3,* from abcd_3_txt union
select 4,* from abcd_4_txt)
where trx_id in (123,321,1234)
as Joe W said in the comment below you can also use name of the table instead of query number, short example:
select tabname, trx_id,refernce number from
(select 'abcd_1_txt' as tabname,* from abcd_1_txt union
...
where trx_id in (123,321,1234)
but both ways don't eliminate duplicates, so you can use union all instead of union. Other way to do that is to run quires separately with the condition
select * from abcd_1_txt where trx_id in (123,321,1234)
select * from abcd_2_txt where trx_id in (123,321,1234)
.
.
.

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;

Union returns two rows if data is different, one if it's the same! Why?

Taking the following statement:
select count( 1 ) as cnt from tbl where val= 1
union
select count( 1 ) as cnt from tbl where val = 0
If the two selects return the same value the result is a single row with that value. If the selects return different values the result is two rows with the two values. Why?
I am trying to find the total count of rows using:
select sum (cnt) from
(
select count( 1 ) as cnt from tbl where value = 1
union
select count( 1 ) as cnt from tbl where value = 0
) as tbl2
which works as expected if the counts are different but gives half the value if the counts are the same...
(PS : More interested in why sql behaves this way than in a solution)
This behavior is by design. You should use UNION ALL to achieve the behavior you want. Basically, UNION performs a set union operation, removing the duplicates in the set.
http://www.fmsinc.com/free/NewTips/SQL/SQLtip5.asp
the main difference between union and union all is that union does a distinct over all fields returned. Where union all just returns and joins the various result sets