Decode function for selecting Tables - sql

Is there any (same or alternate) way of using Table names with the DECODE function.
Something like this:
SELECT * FROM
DECODE(FLAG,1,TABLE1,2,TABLE2,TABLE3)

In SQL the table names cannot be determined at the run time. They need to be provided at the compile time.
If you need to provide the table names dynamically, you will need to use Dynamic SQL.
Hope it Helps
Vishad

select * from table1 where decode(flag, 1,1, 0) = 1 union
select * from table2 where decode(flag, 2,1, 0) = 1 union
select * from table3 where decode(flag, 1,0, 2,0, 1) = 1;

Related

SQL - Run Select Statement Based On Where Query

Hi i want to create a query which does the following. When the paramter 25 is selected it only runs part A of the query, if any other number is selected run both Table A and B select queries.
Example Below:
DECLARE #Type varchar (200)
select * from
(SELECT sort_code FROM dbo.Test 1
WHERE FUNDING_YEAR = 26)
union
(SELECT sort_code FROM dbo.Test 2
WHERE FUNDING_YEAR = 26)
Where case when #Type = 25 then select * from table2 else table 1
You just need to reference the variable in the WHERE clause
SELECT *
FROM TableA
WHERE #Type = 25
UNION
SELECT *
FROM TableB
The query above will always select everything in TableB and will only select everything in TableA when the variable is equal to 25.
Since you are using SSRS, what I would do is write the query to return all of the rows and then apply a filter in the SSRS report when the Paramater is 25. I wouldn't pass a paramater value to the SQL side unless it greatly reduces the run time of the query.
(I would have put this in a comment.)

Multiple Linked Servers in one select statement with one where clause, possible?

Got a tricky one today (Might even just be me):
I have 8 Linked SQL 2012 servers configured to my main SQL server and I need to create table views so that I can filter all these combined table results only using one where clause, currently I use UNION because they all have the same table structures.
Currently my solution looks as follows:
SELECT * FROM [LinkedServer_1].[dbo].[Table] where value = 'xxx'
UNION
SELECT * FROM [LinkedServer_2].[dbo].[Table] where value = 'xxx'
UNION
SELECT * FROM [LinkedServer_3].[dbo].[Table] where value = 'xxx'
UNION
SELECT * FROM [LinkedServer_4].[dbo].[Table] where value = 'xxx'
UNION
SELECT * FROM [LinkedServer_5].[dbo].[Table] where value = 'xxx'
UNION
SELECT * FROM [LinkedServer_6].[dbo].[Table] where value = 'xxx'
UNION
SELECT * FROM [LinkedServer_7].[dbo].[Table] where value = 'xxx'
UNION
SELECT * FROM [LinkedServer_8].[dbo].[Table] where value = 'xxx'
As you can see this is becoming quite ugly because I have a select statement and where clause for each linked server and would like to know if there was a simpler way of doing this!
Appreciate the feedback.
Brakkie101
Instead of using views, you can use inline table-valued functions (a view with parameters). It will not save initial efforts for creating the queries, but could save some work in the future:
CREATE FUNCTION [dbo].[fn_LinkedSever] (#value NVARCHAR(128))
AS
RETURNS TABLE
AS
RETURN
(
SELECT * FROM [LinkedServer_1].[dbo].[Table] where value = #value
UNION
SELECT * FROM [LinkedServer_2].[dbo].[Table] where value = #value
UNION
SELECT * FROM [LinkedServer_3].[dbo].[Table] where value = #value
UNION
SELECT * FROM [LinkedServer_4].[dbo].[Table] where value = #value
UNION
SELECT * FROM [LinkedServer_5].[dbo].[Table] where value = #value
UNION
SELECT * FROM [LinkedServer_6].[dbo].[Table] where value = #value
UNION
SELECT * FROM [LinkedServer_7].[dbo].[Table] where value = #value
UNION
SELECT * FROM [LinkedServer_8].[dbo].[Table] where value = #value
);
Also, if possible, use UNION ALL instead of UNION.

How to define temporary table values in a subquery in Oracle

I am approaching this issue from a non DBA perspective, as in I do not have permissions to create new tables for the database. I am trying to work around this by using a subquery in Oracle kind of like this sudo code:
With temptable as ('col1name', 'col2name', 1,'a',2,'b')
Select * from temptable where col1name = 1
With the temptable looking like
Col1name | Col2name
1 a
2 b
And the output being row 1. I know it is not the easiest way to do it, but it is all I can think of to accomplish my task until I can get the admin to approve a new table. I have searched a lot but I can't find an answer. Is there a simple way to define temporary table data like this?
I would just do this as:
with temptable as (
select 1 as col1name, 'a' col2name from dual union all
select 2, 'b' from dual
)
Select *
from temptable
where col1name = 1;
As an alternative to a CTE (common table expresssion) as suggested by Gordon, you can also use a query as an old-school inline view.
For example:
SELECT tt.col1name
, tt.col2name
FROM ( SELECT 1 AS col1name, 'a' AS col2name FROM DUAL
UNION ALL SELECT 2, 'b' FROM DUAL
UNION ALL SELECT 3, 'c' FROM DUAL
) tt
WHERE tt.col1name = 1
ORDER
BY tt.col1name

Using UNION with Sequel

I want to define a SQL-command like this:
SELECT * FROM WOMAN
UNION
SELECT * FROM MEN
I tried to define this with the following code sequence in Ruby + Sequel:
require 'sequel'
DB = Sequel::Database.new()
sel = DB[:women].union(DB[:men])
puts sel.sql
The result is (I made some pretty print on the result):
SELECT * FROM (
SELECT * FROM `women`
UNION
SELECT * FROM `men`
) AS 't1'
There is an additional (superfluous?) SELECT.
If I define multiple UNION like in this code sample
sel = DB[:women].union(DB[:men]).union(DB[:girls]).union(DB[:boys])
puts sel.sql
I get more superfluous SELECTs.
SELECT * FROM (
SELECT * FROM (
SELECT * FROM (
SELECT * FROM `women`
UNION
SELECT * FROM `men`
) AS 't1'
UNION
SELECT * FROM `girls`
) AS 't1'
UNION
SELECT * FROM `boys`
) AS 't1'
I detected no problem with it up to now, the results seem to be the same.
My questions:
Is there a reason for the additional selects (beside sequel internal procedures)
Can I avoid the selects?
Can I get problems with this additional selects? (Any Performance issue?)
The reason for the extra SELECTs is so code like DB[:girls].union(DB[:boys]).where(:some_column=>1) operates properly. You can use DB[:girls].union(DB[:boys], :from_self=>false) to not wrap it in the extra SELECTs, as mentioned in the documentation.

Using tuples in SQL "IN" clause

I have a table containing the fields group_id and group_type and I want to query the table for all the records having any tuple (group id, group type) from a list of tuples. For example, I want to be able to do something like:
SELECT *
FROM mytable
WHERE (group_id, group_type) IN (("1234-567", 2), ("4321-765", 3), ("1111-222", 5))
A very similar question is already asked at: using tuples in sql in clause , but the solution proposed there presumes the tuple list is to be fetched from another table. This doesn't work in my case is the tuple values are hard coded.
One solution is to use string concatenation:
SELECT *
FROM mytable
WHERE group_id + STR(group_type, 1) IN ("1234-5672", "4321-7653", "1111-2225")
But the problem is that the table is quite big and doing a string concatenation and conversion for each record would be very expensive.
Any suggestion?
Given a very minor tweak (replace double quotes with single and add the VALUES keyword), your proposed syntax is valid Standard SQL-92 syntax i.e.
SELECT *
FROM mytable
WHERE (group_id, group_type) IN (
VALUES ('1234-567', 2),
('4321-765', 3),
('1111-222', 5)
);
Sadly, MSFT have not added it to SQL Server and consider it an 'unplanned' feature.
FWIW PostgreSQL and Sqlite are examples of SQL products that support this syntax.
In SQL Server 2008 you can do like this:
select *
from mytable as T
where exists (select *
from (values ('1234-567', 2),
('4321-765', 3),
('1111-222', 5)) as V(group_id, group_type)
where T.group_id = V.group_id and
T.group_type = V.group_type
)
EDIT: this is a dated answer, although it was the accepted answer in 2011, other answers with more upvotes reflect more recent approaches.
Why not construct the OR statements?
SELECT *
FROM mytable
WHERE (group_id = '1234-567' and group_type = 2)
OR (group_id = '4321-765' and group_type = 3)
OR (group_id = '1111-222' and group_type = 5)
Granted, it doesn't look as nice and neat as your concept example but it will do the job (and if you IN with tuples did exist, it would implement it exactly the same way under the covers most likely.
You can use a common table expression to pretend that these tuples are in another table:
;WITH Tuples as (
select '1234-567' as group_id, 2 as group_type union all
select '4321-765', 3 union all
select '1111-222', 5
)
SELECT * /* TODO - Pick appropriate columns */
from mytable m where exists (
select * from Tuples t
where m.group_id = t.group_id and m.group_type = t.group_type)
Using that solution, this should work:
SELECT *
FROM mytable m
WHERE EXISTS (
SELECT * FROM (
SELECT "1234-567" group_id, 2 group_type UNION ALL
SELECT "4321-765", 3 UNION ALL
SELECT "1111-222", 5) [t]
WHERE m.group_id = t.group_id AND m.group_type = t.group_type)
BTW, you should probably use a CTE to create that inner table.
I haven't seen this yet, but something like this should work
SELECT * FROM AgeGroup ag JOIN
(VALUES
('18-24', 18, 24),
('25-34 ', 25, 39),
('35-44 ', 35, 49),
('45-54 ', 45, 59),
('55-64 ', 55, 69),
('65+ ', 65, 299)
) AS x (agegroup, minage, maxage)
ON ag.age_group = x.agegroup
AND ag.min_age=x.minage
AND ag.max_age=x.maxage
Here is another tuple solution using a join:
SELECT
*
FROM mytable m
JOIN
(
SELECT "1234-567" group_id, 2 group_type
UNION ALL SELECT "4321-765", 3
UNION ALL SELECT "1111-222", 5
) [t]
ON m.group_id = t.group_id
AND m.group_type = t.group_type
I had a similar problem but my tuple collection was dynamic - it was sent over to the SQL Server in a query parameter. I came up with the following solution:
Pass a tuple as an XML:
DECLARE #tuplesXml xml = '<tuples><tuple group-id="1234-567" group-type="2"/><tuple group-id="4321-765" group-type="3"/></tuples>';
Inner join the table that you want to filter with the XML nodes:
SELECT t.* FROM mytable t
INNER JOIN #tuplesXml.nodes('/tuples/tuple') AS tuple(col)
ON tuple.col.value('./#group-id', 'varchar(255)') = t.group_id
AND tuple.col.value('./#group-type', 'integer') = t.group_type
It seems to work fine in my situation which is a bit more complex than the one described in the question.
Keep in mind that it is necessary to use t.* instead of * and the table returned from nodes method needs to be aliased (it's tuple(col) in this case).
select * from table_name where 1=1 and (column_a, column_b) in ((28,1),(25,1))