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

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)

Related

Trying to pull tables from a list to insert into a loop

I'm using an Oracle database where I need to run the same query on a multitude of customer database tables all held in the same database.
The query is a select command and runs as such:
select id from customer1_table name where customer1_table.row = 1234
The problem is, instead of running the command 100 times I'm trying to figure out if I can change cusotmer1 to point to a list with all 100 customer names (they each have a unique name for the same table to denote who belongs where) in a loop statement and each successive run of the loop picks a different customer name and inserts it where needed into the select statement. Any help is GREATLY appreciated.
You can use list selection such as:
SELECT * FROM table1 WHERE ID IN (1,2,3,4,...,1001,1002,...)
Syntax may vary between database types.
You could just use a WITH clause in order to define a scope and just join it:
WITH names_list AS
(
SELECT name1 AS name FROM dual UNION ALL
SELECT name1 FROM dual UNION ALL
...
SELECT nameN FROM dual
)
SELECT name.id
FROM customer1_table name
INNER JOIN names_list nl ON name.name = nl.name;

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;

Column name ambiguous when trying to query multiple tables in BigQuery

I want to query multiple tables, all with the same column names in the same order, and combine the results.
SELECT SUBSTR(arrest_date, 0, 4) arrest_year, *
FROM
`OBTS.circuit11`,
`OBTS.circuit15`,
`OBTS.circuit17`,
`OBTS.circuit19`
WHERE
init_statute LIKE '%3%22%32%' OR
init_statute LIKE '%3%22%34%' OR
LOWER(init_charge_descrip) LIKE '%suspend%';
When I run this BigQuery gives me the following error.
Column name init_statute is ambiguous at [8:3]
How do I query these tables and combine all the resulting rows into one set of results?
I think you are looking for UNION ALL vs CROSS JOIN (note: comma in BigQuery Standard SQL is used for express CROSS JOIN)
So, you most likely looking for below
SELECT SUBSTR(arrest_date, 0, 4) arrest_year, *
FROM (
SELECT * FROM `OBTS.circuit11` UNION ALL
SELECT * FROM `OBTS.circuit15` UNION ALL
SELECT * FROM `OBTS.circuit17` UNION ALL
SELECT * FROM `OBTS.circuit19`
)
WHERE
init_statute LIKE '%3%22%32%' OR
init_statute LIKE '%3%22%34%' OR
LOWER(init_charge_descrip) LIKE '%suspend%'

Column Mismatch in UNION queries

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.

SQL Server : compare two tables with UNION and Select * plus additional label column

I've been playing around with the sample on Jeff' Server blog to compare two tables to find the differences.
In my case the tables are a backup and the current data. I can get what I want with this SQL statement (simplified by removing most of the columns). I can then see the rows from each table that don't have an exact match and I can see from which table they come.
SELECT
MIN(TableName) as TableName
,[strCustomer]
,[strAddress1]
,[strCity]
,[strPostalCode]
FROM
(SELECT
'Old' as TableName
,[JAS001].[dbo].[AR_CustomerAddresses].[strCustomer]
,[JAS001].[dbo].[AR_CustomerAddresses].[strAddress1]
,[JAS001].[dbo].[AR_CustomerAddresses].[strCity]
,[JAS001].[dbo].[AR_CustomerAddresses].[strPostalCode]
FROM
[JAS001].[dbo].[AR_CustomerAddresses]
UNION ALL
SELECT
'New' as TableName
,[JAS001new].[dbo].[AR_CustomerAddresses].[strCustomer]
,[JAS001new].[dbo].[AR_CustomerAddresses].[strAddress1]
,[JAS001new].[dbo].[AR_CustomerAddresses].[strCity]
,[JAS001new].[dbo].[AR_CustomerAddresses].[strPostalCode]
FROM
[JAS001new].[dbo].[AR_CustomerAddresses]) tmp
GROUP BY
[strCustomer]
,[strAddress1]
,[strCity]
,[strPostalCode]
HAVING
COUNT(*) = 1
This Stack Overflow Answer gives me a much cleaner SQL query but does not tell me from which table the rows come.
SELECT * FROM [JAS001new].[dbo].[AR_CustomerAddresses]
UNION
SELECT * FROM [JAS001].[dbo].[AR_CustomerAddresses]
EXCEPT
SELECT * FROM [JAS001new].[dbo].[AR_CustomerAddresses]
INTERSECT
SELECT * FROM [JAS001].[dbo].[AR_CustomerAddresses]
I could use the first version but I have many tables that I need to compare and I think that there has to be an easy way to add the source table column to the second query. I've tried several things and googled to no avail. I suspect that maybe I'm just not searching for the correct thing since I'm sure it's been answered before.
Maybe I'm going down the wrong trail and there is a better way to compare the databases?
Could you use the following setup to accomplish your goal?
SELECT 'New not in Old' Descriptor, *
FROM
(
SELECT * FROM [JAS001new].[dbo].[AR_CustomerAddresses]
EXCEPT
SELECT * FROM [JAS001].[dbo].[AR_CustomerAddresses]
) a
UNION
SELECT 'Old not in New' Descriptor, *
FROM
(
SELECT * FROM [JAS001].[dbo].[AR_CustomerAddresses]
EXCEPT
SELECT * FROM [JAS001new].[dbo].[AR_CustomerAddresses]
) b
You can't add the table name there because union, except, and intersection all compare all columns. This means you can't differentiate between them by adding the table name to the query. A group by gives you control over what columns are considered in finding duplicates so you can exclude the table name.
To help you with the large number of tables you need to compare you could write a sql query off the metadata tables that hold table names and columns and generate the sql commands dynamically off those values.
Derive one column using table names like below
SELECT MIN(TableName) as TableName
,[strCustomer]
,[strAddress1]
,[strCity]
,[strPostalCode]
,table_name_came
FROM
(SELECT 'Old' as TableName
,[JAS001].[dbo].[AR_CustomerAddresses].[strCustomer]
,[JAS001].[dbo].[AR_CustomerAddresses].[strAddress1]
,[JAS001].[dbo].[AR_CustomerAddresses].[strCity]
,[JAS001].[dbo].[AR_CustomerAddresses].[strPostalCode]
,'[JAS001].[dbo].[AR_CustomerAddresses]' as table_name_came
FROM [JAS001].[dbo].[AR_CustomerAddresses]
UNION ALL
SELECT 'New' as TableName
,[JAS001new].[dbo].[AR_CustomerAddresses].[strCustomer]
,[JAS001new].[dbo].[AR_CustomerAddresses].[strAddress1]
,[JAS001new].[dbo].[AR_CustomerAddresses].[strCity]
,[JAS001new].[dbo].[AR_CustomerAddresses].[strPostalCode]
,'[JAS001new].[dbo].[AR_CustomerAddresses]' as table_name_came
FROM [JAS001new].[dbo].[AR_CustomerAddresses]
) tmp
GROUP BY [strCustomer]
,[strAddress1]
,[strCity]
,[strPostalCode]
,table_name_came
HAVING COUNT(*) = 1