Column Mismatch in UNION queries - sql

I have columns A,B in Table 1 and columns B,C in Table 2.Need to perform Union between them .
For example : select A,B from Table 1 UNION select 0,B from Table 2.
I dont need this zero to solve the column mismatch.Instead is there any other solution?
Am asking the question by providing simple example . But in my case the table structure is very large and the queries are already built.Now I need to fix this union query by replacing this zero.(due to DB2 upgrade)
Can anyone help?

For two legs A and B in a union to be union compatible it is required that:
a) A and B have the same number of columns
b) The types for each column in A is compatible with the corresponding column in B
In your query you can use null that is part of every type:
select a, b from T1
UNION
select null, b from T2
Under certain circumstances, you may have to explicitly cast null to the same type as A has (probably not in this case):
select a, b from Table 1
UNION
select cast(null as ...), b from Table 2

A column returned in a SQL result set can only have one data type.
A union or union all results in rows from the first query and the rows of the second query (in case of union they are deduplicated).
So the first column of the first query needs to match the data type of the first column of the second query.
You can check this by running a describe:
describe select a,b from t1
If you work within a GUI (JDBC Connection) you could also use
call admin_cmd('describe select a,b from t1')
So if the some column does not match you have to explicitly cast the data types.

Related

How to make a query where every column is a parallel count of a subquery?

I need to render a query such that every column contains the count of a respective table.
The code I have now is:
SELECT COUNT(table1.Id),
COUNT(table2.Id),
COUNT(table3.Id)
FROM table1,
table2,
table3
WHERE table1.done = 'No' OR
table2.done = 'No' OR
table3.done = 'No' OR
But I need the query to return the same result values as if every table would be counted independently, like:
SELECT COUNT(tableX.Id) FROM tableX WHERE talbeX.done = 'No'
where the 'X' stands for 1,2 or 3.
How can this be achived with SQL?
Thanks beforhand for the help.
Just use a nested sub query, exactly as you have explained it:
SELECT
(SELECT COUNT(table1.Id) FROM table1 WHERE table1.done = 'No') as T1Count,
(SELECT COUNT(table2.Id) FROM table2 WHERE table2.done = 'No') as T2Count,
(SELECT COUNT(table3.Id) FROM table3 WHERE table3.done = 'No') as T3Count,
(SELECT COUNT(tableN.Id) FROM tableN) as TNCount;
This will query the tables independently so you are free to use what ever additional criteria you may need without trying to correlate the results from each query
FROM in this case is not strictly necessary in the outer query as we are not returning rows from any specific table, there is no table that we could specify in the from clause. Each RDBMS has their own convention for these types of queries, MS SQL Server and Oracle are to predominant database engines used in Outsystems
If we did specify a table in FROM then this would return 1 row for every record in that table, which is inefficient and not required. So it is important that we do not include a FROM clause.
Transact-SQL - FROM
The FROM clause is usually required on the SELECT statement. The exception is when no table columns are listed, and the only items listed are literals or variables or arithmetic expressions.
ORACLE - DUAL Table
DUAL is a table automatically created by Oracle Database along with the data dictionary. DUAL is in the schema of the user SYS but is accessible by the name DUAL to all users. It has one column, DUMMY, defined to be VARCHAR2(1), and contains one row with a value X. Selecting from the DUAL table is useful for computing a constant expression with the SELECT statement. Because DUAL has only one row, the constant is returned only once. Alternatively, you can select a constant, pseudocolumn, or expression from any table, but the value will be returned as many times as there are rows in the table.
Update - OP is using Oracle!
After attempting the solution, OP responded that it raised the following error:
Error in advanced query SQL2: ORA-00923: FROM keyword not found where expected
The ORA prefix of this error number indicates that the data store is actually an Oracle implementation, so we need to append the FROM DUAL to the query.
SELECT
(SELECT COUNT(table1.Id) FROM table1 WHERE table1.done = 'No') as T1Count,
(SELECT COUNT(table2.Id) FROM table2 WHERE table2.done = 'No') as T2Count,
(SELECT COUNT(table3.Id) FROM table3 WHERE table3.done = 'No') as T3Count,
(SELECT COUNT(tableN.Id) FROM tableN) as TNCount
FROM DUAL;

How to select the nth column, and order columns' selection in BigQuery

I have this huge table upon which I apply a lot of processing (using CTEs), and I want to perform a UNION ALL on 2 particular CTEs.
SELECT *
, 0 AS orders
, 0 AS revenue
, 0 AS units
FROM secondary_prep_cte WHERE purchase_event_flag IS FALSE
UNION ALL
SELECT *
FROM results_orders_and_revenues_cte
I get a "Column 1164 in UNION ALL has incompatible types : STRING,DATE at [97:5]
Obviously I don't know the name of the column, and I'd like to debug this but I feel like I'm going to waste a lot of time if I can't pin-point which column is 1164.
I also think this is a problem of the order of columns between the CTEs, so I have 2 questions:
How do I identify the 1164th column
How do I order my columns before performing the UNION ALL
I found this similar question but it is for MSSQL, I am using BigQuery
You can get information from INFORMATION_SCHEMA.COLUMNS but you'll need to create a table or view from the CTE:
CREATE OR REPLACE VIEW `project.dataset.secondary_prep_view` as select * from (select 1 as id, "a" as name, "b" as value)
Then:
SELECT * FROM dataset.INFORMATION_SCHEMA.COLUMNS WHERE table_name = 'secondary_prep_view';

Oracle UNION ALL not returning full set

I have two tables that are populated with the same structure into 2 different tables: MST3_CURR and MST4_CURR. Accounts are populated into one of the two tables; each table holds accounts that are in a different 'state'. In order to generate a complete list of accounts the tables need to be fully joined and have the most current data for an account pulled.
There are several other tables which follow the exact same approach where I am using a UNION ALL operator without issue. However, for some reason with these two tables when I perform the UNION ALL I receive the record for account 4700121500023998 which is found in MST3_CURR, but the other accounts are in MST4_CURR and are not present in the final dataset. When I reverse the UNION ALL order and have MST4_CURR first followed by MST3_CURR the reverse is true.
WITH cchm_d_curr AS (
SELECT * FROM hcus_raw.cchm_d_mst3_curr
UNION ALL
SELECT * FROM hcus_raw.cchm_d_mst4_curr
)
SELECT chd_current_balance FROM cchm_d_curr
WHERE
chd_account_number IN (4700121500023998, 4700121500090430, 4700121500044101, 4700121500250492, 4700121500250013)
;
I have am at a loss to finding any kind of answer to this peculiar behaviour that Oracle 12c is exhibiting. Please let me know if there is information missing that would help answer my question.
Thank you.
It might be that order of columns in the queried tables is different, so reversing tables in the union leads to different columns to be filtered by "where", i.e.
select a, b
from (select A, b from t1
union all
select b, A from t2)
where a=1
returns something different from what expected from this query
select a, b
from (select A, b from t1
union all
select A, b from t2)
where a=1
I would check if columns order in tables hcus_raw.cchm_d_mst3_curr and hcus_raw.cchm_d_mst4_curr in the original question is same.
what does the following return [m3 first, then m4 first]??
{
WITH cchm_d_curr AS (
SELECT 'm3' src, m3.* FROM hcus_raw.cchm_d_mst3_curr m3
UNION ALL
SELECT 'm4' src, m4.* FROM hcus_raw.cchm_d_mst4_curr m4
)
SELECT src, chd_account_number, chd_current_balance FROM cchm_d_curr
WHERE
chd_account_number IN (4700121500023998, 4700121500090430, 4700121500044101, 4700121500250492, 4700121500250013)
;
}

The number of columns in the two selected tables or queries of a Union query do not match

I have been facing error in MS Access and error is "The number of columns in the two selected tables or queries of a Union query do not match."
Here is my SQL query:
SELECT sale_head.suppliername AS sale_head_suppliername,
sale_head.invoiceno AS sale_head_invoiceno, sale_head.invoicedate,
sale_details.invoiceno AS sale_details_invoiceno, sale_details.suppliername AS sale_details_suppliername,
sale_details.product_code, sale_details.qty, sale_details.totalkg, sale_details.Rate, sale_details.subtotal FROM sale_head
INNER JOIN sale_details ON sale_head.[invoiceno] = sale_details.[invoiceno]
UNION ALL select 'Total', sum(sale_details.subtotal) from sale_details
WHERE (((sale_head.suppliername)='Ramkrishna Creation'));
Am I missing something ? If yes please do let me know.
When you union two or more queries together each query should have the same columns of data with same data type for example :
SELECT Name,LastName,SUM(Salary) FROM tabel1
UNION
SELECT Text1,Text2,SomeMoney FROM table2
is valid (assuming that Name and Text1,LastName and Text2 and Sum of salary and SomeMoney have the same data type but :
SELECT Name,LastName,SUM(Salary) FROM tabel1
UNION
SELECT Text1,SomeMoney FROM table2
(cloumns count mismatch)or
SELECT Name,LastName,SUM(Salary) FROM tabel1
UNION
SELECT Text1,SomeMoney,Text2 FROM table2
(data type mismatch)are not valid union statements.
UPDATE : My answer is according to SQL Standard Definition of Union Statement which states :
The UNION operator is used to combine the
result-set of two or more SELECT statements.
Notice that each SELECT statement within the UNION must have the same
number of columns. The columns must also have similar data types.
Also, the columns in each SELECT statement must be in the same order.
In a UNION, both datasets must have the same number of columns but they don't need to be the same datatype
All queries in a UNION operation must request the same number of fields; however, the fields do not have to be of the same size or data type.
UNION Operation (Microsoft Access SQL)

return a default row in sql

Is it possible in oracle sql to return a default row if no rows found.
I have a process where in rows fetched will be put in a flat ascii file.
now i have a requirement that if there are no rows fetched by the sql query then there should be a default row in the ascii file.
is it possible in sql to output a default row if no rows fetched by the query
note: i dont want to use pl/sql.
For complex queries where the overhead on finding out if there is a row in the result set is onerous or the query is just very large and unwieldy, then a subquery factoring clause might be beneficial:
With my_query as
(
select a, b, c from foobar where foo='FOO'
)
Select a,b,c
From my_query
Union All
Select ...
From dual
Where Not Exists
(Select 1 from my_query)
/
You could use UNION ALL for this:
select a, b, c from foobar
where foo='FOO'
union all
select 'def', 'ault', 'value' from dual
where not exists ( select 'x' from foobar where foo='FOO' )
I suspect that it would be cleaner to have the process that the writes the ASCII file write the default data if no rows are returned rather than getting Oracle to do it. If the query that you're using is expensive, you'd significantly increase that cost if you fudge it to return a default row as ammoQ and David Oniell have done.
There is another (sad, twisted) option. No CTEs or subquery repetition needed.
select
coalesce(a, 'def'),
coalesce(b, 'ault'),
coalesce(c, 'value')
from foobar
right join (select 1 from dual) on 1=1
where foobar.some_condition;