Mixing UNION ALL and DISTINCT in SQL - sql-server

I have a SQL Server 2014 database. I am building a stored procedure that will return counts across several tables that match certain criteria. At this time, I have the following:
SELECT 'Table1' TableName, COUNT(0) TotalRows FROM dbo.[SomeTable]
UNION ALL
SELECT COUNT(DISTINCT [Name]) AS 'Department' FROM [Department]
UNION ALL
SELECT COUNT(DISTINCT [SubDepartment]) AS 'SubDepartment' FROM [Department]
UNION ALL
SELECT 'Table2' TableName, COUNT(0) TotalRows FROM dbo.[AnotherTable]
When I execute this SQL, I get an error that says:
All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists.
If I remove the two lines that begin with SELECT COUNT(... it works just fine. However, I need to get the number of department names and the number of sub-department names. How can I do this while still getting the counts from the other tables?
Thanks!

Related

SQL how to find distinct values between two tables?

We have an internal and an external table. The internal table is actually a copy of the external table with some fields renamed and they are roughly the same. For some reason, the data in the internal table might not match the external table because of inappropriate operation. Here is the case:
SELECT COUNT(*) AS [Total Rows]
FROM [dbo].[Auct_Car_Ex];
-- (ANS.) 76716
SELECT COUNT(*) AS [Total Rows]
FROM [dbo].[Auct_Car];
-- (ANS.) 76716
They have the same number of rows.
SELECT COUNT(DISTINCT([HORSEPOWER]))
FROM [dbo].[Auct_Car_ex];
-- (ANS.) 459
SELECT COUNT(DISTINCT([Horsepower]))
FROM [dbo].[Auct_Car];
-- (ANS.) 458
However, the number of distinct Horsepower is different. I'd like to know which value of HORSEPOWER exists in Auct_Car_ex but not in Auct_Car. How can I find it?
Just use EXCEPT
SELECT acx.HORSEPOWER
FROM dbo.Auct_Car_ex acx
EXCEPT
SELECT ac.Horsepower
FROM dbo.Auct_Car ac;
yes,it is easy by sub-query.
SELECT [HORSEPOWER]
FROM [dbo].[Auct_Car_ex]
WHERE [HORSEPOWER] NOT IN (
SELECT [Horsepower]
FROM [dbo].[Auct_Car]
GROUP BY [Horsepower]
)
GROUP BY [HORSEPOWER]
This looks like a case for not exists
select horsepower
from Auct_Car_ex x
where not exists (
select * from Auct_Car a
where a.horsepower = x.horsepower
);

COUNT(1) in DB2

I have query where there is COUNT(1) in select statement.
I want to know what does it return. COUNT(*) will return the number of rows but COUNT(1) I have no idea. I tried to execute one statement in DB2 but got error saying COLUMN OR EXPRESSION IN THE SELECT LIST IS NOT VALID.
Post your SQL statement.
I suspect you have something like
select customer, count(1)
from salesHistory
In which case, DB2 isn't complaining about count(1) which is perfectly valid; but it's complaining because you've got a aggregate function in the select list along with a non-aggregate column. In order to do that, you have to include a GROUP BY clause.
select customer, count(1)
from salesHistory
group by customer

Summarizing count of multiple talbes in one row or column

I've designed a migration script and as the last sequence, I'm running the following two lines.
select count(*) from Origin
select count(*) from Destination
However, I'd like to present those numbers as cells in the same table. I haven't decided yet if it's most suitable to put them as separate rows in one column or adjacent columns on one row but I do want them in the same table.
How can I select stuff from those selects into vertical/horizontal line-up?
I've tried select on them both with and without parentheses but id didn't work out (probably because of the missing from)...
This questions is related to another one but differs in two aspects. Firstly, it's much more to-the-point and clearer states the issue. Secondly, it asks about both horizontal and vertical line-up of the selected values whereas the linked questions only regards the former.
select
select count(*) from Origin,
select count(*) from Destination
select(
select count(*) from Origin,
select count(*) from Destination)
You need to nest the two select statements under a main (top) SELECT in order to get one row with the counts of both tables:
SELECT
(select count(*) from Origin) AS OriginCount,
(select count(*) from Destination) AS DestinationCount
SQLFiddle for the above query
I hope this is what you are looking for, since the "same table" you are mentioning is slightly confusing. (I'm assuming you're referring to result set)
Alternatively you can use UNION ALL to return two cells with the count of both tables.
SELECT COUNT(*), 'Origin' 'Table' FROM ORIGIN
UNION ALL
SELECT COUNT(*), 'Destination' 'Table' FROM Destination
SQLFiddle with UNION ALL
SQLFiddle with UNION
I recommend adding the second text column so that you know the corresponding table for each number.
As opposed to simple UNION the UNION ALL command will return two rows everytime. The UNION command will generate a single result (single cell) if the count of rows in both tables is the same (the same number).
...or if you want vertical...
select 'OriginalCount' as Type, count(*)
from origin
union
select 'DestinationCount' as Type, count(*)
from destination

Conversion failed when converting date and/or time from character string. UNION CTE

I've been given a view to troubleshoot. It begins with a CTE that gets all values of a surrogate key used in several tables with UNIONs between each query. It then uses this CTE as an INNER JOIN to select data about those surrogate keys. The query is like the following code:
WITH emp AS (
SELECT DISTINCT EmployeeSk FROM view1
UNION
SELECT DISTINCT EmployeeSK FROM Table1
UNION
--then there are two views that if you include BOTH, the overall query fails
SELECT DISTINCT EmployeeSK FROM view2
UNION
SELECT DISTINCT EmployeeSK FROM View3 )
SELECT Col1, col2, col3
FROM Table2 t2
INNER JOIN emp
ON t2.EmployeeSK = emp.EmployeeSK
Whenever you use the CTE, users get the error:
Msg 241, Level 16, State 1, Line 22
Conversion failed when converting date and/or time from character string.
If you select each query separately all are returning INTs. In fact, I double checked each query by running the following query against each source:
SELECT DISTINCT SQL_VARIANT_PROPERTY(<tableSK>, 'BaseType') FROM <source Table or view>
All queries report that all columns returned are INT.
I have also created a #tempTable:
CREATE TABLE #tmp ( SurrogateKey INT)
Then inserted each query into the #tempTable and all inserts work. All values are INTs. The values range from -1 to 16435.
I can get all the queries to work with the UNION as long as I return one of two of the queries. If I remove either of these queries the CTE and UNION statements will work, but I cannot use both. The values for these two queries are also INTs and have values from -1 to 16435 too.
I'm at a loss as to why I get this error. Other than re-writing the view to be a stored procedure, and putting the values into a temp table, what could I try?

How to use UNION while inserting in a table using SELECT clause from many tables in SQL Server 2000

I am using SQL Server 2000. I have multiple criterias which i have to use to extract different sets of records from mumtiple table in another table. I am using
INSERT INTO T1(A,B)
(SELECT E,R FROM T2)
UNION
(SELECT Z,X FROM T3)
Query analyzer is throwing error that while using UNION, you should use ORDER BY clause with SELECT. Even after doing that i m not able to union two different queries which are returing same columns in their select clause.
What is the right way to insert using SELECTS with UNIONS and ORDER BY.
The pseudo is too cryptic (reduced?)
It is very unlikely to get 2 columns per cross join of 2 tables in each of the union components
INSERT INTO T1(A,B)
(SELECT * FROM E,R)
UNION
(SELECT * FROM Z,X)
Note: If you have ANY order by clause at all, it must be at the end of the union
INSERT T1(A,B)
SELECT P,Q FROM E,R
UNION
SELECT R,S FROM Z,X
#updated based on error text "Server: Msg 104, Level 15, State 1, Line 1 ORDER BY items must appear in the select list if the statement contains a UNION operator"
This occurs when you have a union that attempts to perform ORDER BY on a column that does not appear in the result. Consider a normal ORDER BY involving non-selected columns
select top 10 name from syscolumns order by xtype
The rows are consistent and the query can be satisfied. However, if you did
select top 10 name from syscolumns where xtype > 50
union all
select top 10 name from syscolumns where xtype < 50
order by xtype
EVEN IF xtype exists in both parts of the UNION, but the time it gets presented to ORDER BY (which works at the END over the entire result set), the column is not there. You would have to rewrite it (if you didn't want to show xtype) as
select name from (
select top 10 name, xtype from syscolumns where xtype > 50
union all
select top 10 name, xtype from syscolumns where xtype < 50
) x
order by xtype
Hope that helps

Resources