Alias names in union / union all query - SQL Server - sql-server

I have a simple sql statements as below
CASE 1:
select 1 as a
union
select 2 as a
Output: This case is working as expected
CASE 2:
select 1 as a
union
select 2 as b
Output: Though the alias is 'b' in my second select, it still shows the alias 'a'.
Why cant it take the alias from the second select statement?
How can we make sql to choose the alias from the second select query?
CASE 3:
select 1
union
select 2 as b
Output: Even though my first select statement above does not have any alias name but the second one still have, why the result still shows 'No column name'?

Lets try to teach something useful here. It is not just It's because that's how it is. There is a pattern definition that stipulate the rules for the SQL language and it is called SQL ANSI. You can see a timeline of this definition here: Database Administration - ANSI SQL Standards and Guidelines
The reason behind this definition is simple to understand. Since a UNION operation transform the result of two queries into one, some rules must be applied like the definition of the fields name, the types of the fields (in order they are select) and some others.
The alias part works just for the first one because there is no way for the database to identify which column would be the right one in a union operation as you will get one row per result:
select 1 as a
UNION
select 2
This will result in:
a
1
2
Since it is showed as ROWS how the database would work if it name each column for each SQL in the UNION stack?
-a
1
-b
2
That's why the rule of the first query alias is applied.
The SQL ANSI document is not free although if you dig enough you may find earlier versions of it in PDF. Good luck with that :) (hint: I have an answer in my profile with a working link ;) )

You could wrap everything around a single SELECT and alias that column with what you want.
select a as [b] -- just alias it here with whatever you want
from (
select 1 as a
union
select 2 as b
...) result_set
But as #Will said, it is what it is, can't change that.
OR:
Just make sure that you use the query with the "alias" that you want at the top and UNION that with a single SELECT statement that contains other queries / values you have.
select 2 as b
union
select a
from (
select 1 as a
union
select 3 as c
union
... ) result_set

Related

Order by in union clause

Could any one please help me I have been working on a query containing unions n joins of multiple tables.. I have got the desired results but I want to get these results in some specific order so the whole result is being orderd according to one column.
Here is the snippet of code I am working on:
select name, age
from UserUni
order by age
union all
select age, Name
from UserOffice
order by age
Just add an ORDER BY clause at the very end of the UNION query, and it should be applied to the entire query:
select name, age
from UserUni
union all
select name, age
from UserOffice
order by age
Note that I swapped the order of the columns appearing in the second half of the UNION query because it doesn't make sense to put age and name into the same column. It is generally a requirement in a UNION query that the types and number of all columns be the same in boths halves of the query. One exception might be MySQL, which might appear to allow mixing numbers and text, but even in this case some implicit type conversion would be happening underneath the hood.
when we are using we can not use order by with both statements. because union at the end give one result end so how is it possible to use two order by statements.
you can check details here.
https://finalcodingtutorials.blogspot.ae/2017/03/order-by-clause-with-union-in-sql-server.html
hopefully it will resolve your issue will let you know complete details or union and order by statement.

Select Union in SphinxQL?

Is it possible to do any sort of Union using SphinxQL? I want to return one set of results containing two queries and in order of the query. A simple example would be:
Select Author from idx_jobs where MATCH('#(Author) Steinbeck')
Union Select Author from idx_jobs where MATCH('#(Description) Steinbeck')
Naturally I could do
Select Author from idx_jobs where MATCH('#(Author, Description) Steinbeck')
but I'm trying to provide some control over 'relevance' in the results.
No union.
But seems like field weight would be useful
http://sphinxsearch.com/docs/current.html#sphinxql-select
.... OPTION field_weights=(author=1000)
Should put the matches against the author field first. (ie add that to end of second query)

Group by an evaluated field (sql server) [duplicate]

Why are column ordinals legal for ORDER BY but not for GROUP BY? That is, can anyone tell me why this query
SELECT OrgUnitID, COUNT(*) FROM Employee AS e GROUP BY OrgUnitID
cannot be written as
SELECT OrgUnitID, COUNT(*) FROM Employee AS e GROUP BY 1
When it's perfectly legal to write a query like
SELECT OrgUnitID FROM Employee AS e ORDER BY 1
?
I'm really wondering if there's something subtle about the relational calculus, or something, that would prevent the grouping from working right.
The thing is, my example is pretty trivial. It's common that the column that I want to group by is actually a calculation, and having to repeat the exact same calculation in the GROUP BY is (a) annoying and (b) makes errors during maintenance much more likely. Here's a simple example:
SELECT DATEPART(YEAR,LastSeenOn), COUNT(*)
FROM Employee AS e
GROUP BY DATEPART(YEAR,LastSeenOn)
I would think that SQL's rule of normalize to only represent data once in the database ought to extend to code as well. I'd want to only right that calculation expression once (in the SELECT column list), and be able to refer to it by ordinal in the GROUP BY.
Clarification: I'm specifically working on SQL Server 2008, but I wonder about an overall answer nonetheless.
One of the reasons is because ORDER BY is the last thing that runs in a SQL Query, here is the order of operations
FROM clause
WHERE clause
GROUP BY clause
HAVING clause
SELECT clause
ORDER BY clause
so once you have the columns from the SELECT clause you can use ordinal positioning
EDIT, added this based on the comment
Take this for example
create table test (a int, b int)
insert test values(1,2)
go
The query below will parse without a problem, it won't run
select a as b, b as a
from test
order by 6
here is the error
Msg 108, Level 16, State 1, Line 3
The ORDER BY position number 6 is out of range of the number of items in the select list.
This also parses fine
select a as b, b as a
from test
group by 1
But it blows up with this error
Msg 164, Level 15, State 1, Line 3
Each GROUP BY expression must contain at least one column that is not an outer reference.
There is a lot of elementary inconsistencies in SQL, and use of scalars is one of them. For example, anyone might expect
select * from countries
order by 1
and
select * from countries
order by 1.00001
to be a similar queries (the difference between the two can be made infinitesimally small, after all), which are not.
I'm not sure if the standard specifies if it is valid, but I believe it is implementation-dependent. I just tried your first example with one SQL engine, and it worked fine.
use aliasses :
SELECT DATEPART(YEAR,LastSeenOn) as 'seen_year', COUNT(*) as 'count'
FROM Employee AS e
GROUP BY 'seen_year'
** EDIT **
if GROUP BY alias is not allowed for you, here's a solution / workaround:
SELECT seen_year
, COUNT(*) AS Total
FROM (
SELECT DATEPART(YEAR,LastSeenOn) as seen_year, *
FROM Employee AS e
) AS inline_view
GROUP
BY seen_year
databases that don't support this basically are choosing not to. understand the order of the processing of the various steps, but it is very easy (as many databases have shown) to parse the sql, understand it, and apply the translation for you. Where its really a pain is when a column is a long case statement. having to repeat that in the group by clause is super annoying. yes, you can do the nested query work around as someone demonstrated above, but at this point it is just lack of care about your users to not support group by column numbers.

Issue in union operation

I have a query in database like
SELECT 0 AS [DocumentType],'Select Document Type' [DocumentTypeX],0 ,0
UNION
SELECT dbo.tbDocumentType.*
FROM dbo.tbDocumentType where Site=#Site
It throws error message "All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists."
First and foremost rule for UNION Operation:
1.Both Query should have the same number of the resultset.
2.Respective Columns of both queries should have similar data types.
3.Never go with TableName.*.Instead Specify Column Names
Please check on that....
Instead of
SELECT dbo.tbDocumentType.*
Select the columns matching your UNION fields
SELECT dbo.tbDocumentType.[DocumentType],
dbo.tbDocumentType.[DocumentTypeX],
dbo.tbDocumentType.[Something1],
null -- Or use any value you want if doesnt have the column

SSRS 2008 SUM using scope and recursive option to rollup values

Consider this data (6 rows and 1 column for now)
;with cols as
(
SELECT 1 colID, 'C1' col
--UNION SELECT 2, 'C2'
)
, rows as
(
SELECT 1 RowID, 'R1' row, null ParentID
UNION SELECT 2, 'R2', 1
UNION SELECT 3, 'R3', 2
UNION SELECT 4, 'R4', 2
UNION SELECT 5, 'R5', 1
UNION SELECT 6, 'R6', 1
)
,data
AS
(
SELECT 3 RowID, 1 as Amount
UNION SELECT 4 RowID, 2 as Amount
)
SELECT r.RowID, r.row, c.colID, c.col, d.Amount, r.ParentID
FROM rows r
CROSS JOIN cols c
LEFT JOIN data d on d.RowID = r.RowID
I apply this to a matrix control using the following layout and get the output as shown. Notice how the amounts are not rolled up to the parent rows. THis is ok for now.
Now, to get the values to roll up I can use the expression (well documented by msdn, blogs, etc)
=Sum(Fields!Amount.Value, "RowGroup", recursive)
This now gives me exactly what I want, with the values rolling up to their parent rows:
However, my dataset has dynamic column as well as rows but when a second (or third, forth, etc) column is introduced the recursive sum doesn't work as I expect. Instead of staying within the scope of the current column it sums all the columns and then rolls those values up to the parent lines. as shown:
I want the values to only get rolled up within the current scope of a given row and column.
Any guidance would be greatly appreciated as this has stumped me.
Thanks
This isn't actually possible due to needing to look at both the row group scope and the column group scope..
I spent a long time searching for an answer.. For anyone else looking. here are some better explanations from other forums:
https://social.msdn.microsoft.com/Forums/sqlserver/en-US/55c55aad-4755-4da5-afce-94d16c9e201d/cannot-perform-a-correct-recursive-sum-in-a-tablix?forum=sqlreportingservices
Unfortunately, the scenario you described is not supported so far (both 2008 and 2005), because it cannot do Recursive sum in two scopes in a matrix. If you replace the expression with SUM(Fields!Amount.Value, "NAME", Recursive), you will get the recursive total, but the tota willl ignore the monthindex group. Actually, you want to recursive sum for both groups NAME and MonthIndex, however you cannot write expression like this: SUM(Fields!Amount.Value, "NAME" and MonthIndex, Recursive). Right? So generally speaking, in a matrix, when you write the expression like this: SUM(Fields!Amount.Value) It will sum in the scope of two groupsNAME and MonthIndex, and if you want to specify the scope, you have to specify only one scope. And unfortunately, the recursive sum needs to specify the scope and scenario you described needs to specify two scopes
https://social.msdn.microsoft.com/Forums/sqlserver/en-US/9d7f36bc-73d6-4f19-a306-0b84321e6feb/calculating-the-sum-on-a-hierarchy-with-multiple-grouping-columns?forum=sqlreportingservices

Resources