Add a string to SQL select - sql

I am using SQL reporting service and working on paramters. One of paramters contains a list of cities. So, I have a dataset that
select city from MyCities
What I would like to do is to add a string for selecting all cities. So, I modifed the query to do something like
select city from Mycities union select 'ALL'
Only problem with this is that I want to show on the top of list so that it will be first itme on the list.
Is there a way I can sort the list so that it shows "All" first and followed by the name of actual cities?
Thanks.

Could you not do select 'ALL' union select city from Mycities

SELECT City
FROM
(
SELECT City, 1 AS Sorter FROM MyCities
UNION ALL
SELECT 'ALL' AS City, 0 AS Sorter
) iq
ORDER BY iq.Sorter ASC

I do this a lot and typically just wrap it with special characters, so that it stands out as well:
SELECT City
FROM (
SELECT City
FROM MyCities
UNION SELECT '<<ALL>>'
) X
ORDER BY City;
That will push it to the top of the list

Sure, it would be something like:
select 'ALL'
union
select city from Mycities
However you may receive a message about the amount of columns, so you may have to add blank '' to make it fit.

This would work to:
select 1 as id,'All' as city
union all
select 2,city from mycities
order by id,name

I think select 'ALL' union select city from Mycities actually works, but at any rate it isn't guaranteed, so you can do:
Select city
from (Select 'ALL' as city, 1 as myOrder
union
select city,2 as myOrder from Mycities)
order by myOrder

Related

Case statement to determine if I should union

I currently want to do some sort of conditional union. Given the following example:
SELECT age, name
FROM users
UNION
SELECT 25 AS age, 'Betty' AS name
Say I wanted to only union the second statement if the count of 'users' was >=2 , otherwise do not union the two.
In summary I want to append a table with a row if the table only has 2 or more values.
You could use an ugly hack something like this, but I think Tim's answer is better:
SELECT age, name
FROM users
UNION ALL
SELECT 25, 'Betty'
WHERE (SELECT COUNT(*) FROM users) > 1;
If it's in a stored-procedure you could use If...Else:
IF (SELECT COUNT(*) FROM users) < 2
BEGIN
SELECT age, name
FROM users
END
ELSE
SELECT age, name
FROM users
UNION ALL
SELECT 25 AS age, 'Betty' AS name
Otherwise you could try something like this:
SELECT age, name
FROM users
UNION ALL
SELECT TOP 1 25 AS age, 'Betty' AS name
FROM users
WHERE (SELECT COUNT(*) FROM users) >= 2
Note that i've used UNION ALL since it doesn't seem that you want to eliminate duplicates.
Played around here: http://sqlfiddle.com/#!6/a7540/2323/0
Edit: Instead of my second approach i prefer Zohar's. So if you can use If....Else prefer that otherwise WHERE (SELECT COUNT(*) FROM users) > 1 without a table.
Something like the following should work:
SELECT age, name
FROM users
UNION ALL
SELECT age, name
FROM (SELECT 25 AS age, 'Betty' AS name) x
CROSS APPLY (SELECT COUNT(*) FROM users) y(cnt)
WHERE y.cnt >= 2
Second part of UNION ALL will be NULL in case users table has less than 2 records.
SELECT age
, name
FROM users
UNION
SELECT 25 As age
, 'Betty' As name
WHERE EXISTS (
SELECT Count(*)
FROM users
HAVING Count(*) >= 2
)
;

How can I add a "custom" row to the top of a select result set?

I can select and pull out a list of records by using a select statement like so with t-sql:
select * from [dbo].[testTable];
But how can I add in a "custom" row to the top of the result set?
For example, if the result set was:
John john#email.com
Max max#domain.com
I want to add a row, which is not from the table, to the result set so that it looks like so:
Name Email
John john#email.com
Max max#domain.com
The reason why I want to do this is because I'm going to export this into a csv file through sqlcmd and I want to add in those "custom row" as headers.
This is the safe way to do this:
select name, email
from ((select 'name' as name, 'email' as email, 1 as which
) union all
(select name, email, 2 as which from [dbo].[testTable]
)
) t
order by which;
In practice, union all will work:
select 'name' as name, 'email' as email
union all
select name, email from [dbo].[testTable]
However, I cannot find documentation that guarantees that the first subquery is completed before the second. The underlying operator in SQL Server does have this behavior (or at least it did in SQL Server 2008 when I last investigated it).
SELECT name, email FROM (
SELECT 'Name' AS Name, 'Email' AS Email, 1 AS o
UNION ALL
SELECT name, email, 2 AS o FROM testTable
) t
ORDER BY o, name
The o column is added to order the result sets of the UNION so that you ensure the first result set appears on top.
SELECT * FROM
(SELECT 'Name' as name, 'Email' as email, 1 'rank'
union
SELECT name, email,3 'rank')a
ORDER BY a.rank,a.name
Try the above.

Oracle SQL - fetching a record at last

SELECT * FROM
(
SELECT city from addr_tab
UNION ALL
SELECT 'zzzz' AS city from dual
)ORDER BY city
I am using the above approach to retrieve the 'zzzz' as last record of the table. But I don't think this would work all the time, as the city theoretically might be something bigger than "zzzz" alphabetically. Is there any other robust approach to get this harcoded record as the last record?. I need this for reporting using oracle reports. Any help would be most welcome.
Add another virtual column (order_col) to use for ordering.
The query would end up something as follows.
SELECT * FROM
(
SELECT city, 1 as order_col from addr_tab
UNION ALL
SELECT 'zzzz', 2 as order_col AS city from dual
)ORDER BY order_col, city
THis way you can guarantee that 'zzzz' will always be last since the primary ordering column (order_col) is guaranteed to have a lower value for 'zzzz' than for all the rest of the records.
Well, as others have said (in comment and answer) there is probably a better way to approach the problem from the beginning; but if you need a temporary hack read on!...
Call the last record whatever you want...
'zzzz' is fine...
and then use a custom ORDER BY like:
SELECT *
FROM (
SELECT city
FROM addr_tab
UNION ALL
SELECT 'zzzz' AS city
FROM dual
)
ORDER BY
CASE WHEN city = 'zzzz' THEN 1 ELSE 0 END,
city;
this can be solve by following query also
SELECT * FROM
( SELECT city from addr_tab order by city)
UNION ALL
SELECT 'zzzz' from dual;
now got one more style to do this
with
b1 as
(
SELECT city from addr_tab order by city
)
select city from b1
union all
SELECT 'zzzz' from dual;
so any one you can use ....

Get data origin after a UNION

I have a SQL query like this:
SELECT *
FROM (
(SELECT name FROM man)
UNION
(SELECT name FROM woman )
) AS my_table
ORDER BY name
how can I retrieve the source of my data?
For example if my result is like this:
Bob
Alice
Mario
...
I want to know if the name 'Bob' is retrieve from the 'man' table or from the 'woman' table.
SELECT *
FROM (
(SELECT name, 'man' as source FROM man)
UNION ALL
(SELECT name, 'woman' FROM woman )
) AS my_table
ORDER BY name
I added the UNION ALL becasue if these are mutually exclusive tables, it will be faster. If they are not, then adding the source will make the results mutually exclusive and you wil be able to see where the dups are. If they are not mutually exclusive but you only want to show one record, what business rule do you want to show which record you took?
A select can include a literal string, so the simplest way is probably to do:
SELECT *
FROM (
(SELECT name, 'man' as source FROM man)
UNION
(SELECT name, 'woman' as source FROM woman )
) AS my_table
ORDER BY name
These will only work if there is no intersection of Man & Woman.
If you expect duplicates, you will need to add some magic to the where clause.
and perhaps a 3rd query in the union to cover those where both exist.

Add row to query result using select

Is it possible to extend query results with literals like this?
select name from users
union
select name from ('JASON');
or
select age, name from users
union
select age, name from (25,'Betty');
so it returns all the names in the table plus 'JASON', or (25,'Betty').
You use it like this:
SELECT age, name
FROM users
UNION
SELECT 25 AS age, 'Betty' AS name
Use UNION ALL to allow duplicates: if there is a 25-years old Betty among your users, the second query will not select her again with mere UNION.
In SQL Server, you would say:
Select name from users
UNION [ALL]
SELECT 'JASON'
In Oracle, you would say
Select name from user
UNION [ALL]
Select 'JASON' from DUAL
is it possible to extend query results with literals like this?
Yes.
Select Name
From Customers
UNION ALL
Select 'Jason'
Use UNION to add Jason if it isn't already in the result set.
Use UNION ALL to add Jason whether or not he's already in the result set.