How to use CASE or IF-statement in Postgres to select from different table? - sql

I want to make a selection from one of many tables. This selection depends on some condition. How can I make it?
I suppose it should be some like this (but it doesn't work):
CASE x
WHEN x=1 THEN
select Id,Name from table1
WHEN x=2 THEN
select Id,Name from table2
WHEN x=3 THEN
select Id,Name from table3
END CASE;

Inefficient solution the queries all 3 tables, but immitates a switch statement in code (assuming the retrieved columns are equivalent)
declare #inputValue int = 1
SELECT * FROM (
SELECT 1 [key], Id from table1
UNION ALL
SELECT 2, Id from table2
UNION ALL
SELECT 3, Id from table3
) x
where x.[key] = #inputValue

One way to do it:
SELECT id, name
FROM table1
WHERE x = 1
UNION ALL
SELECT id, name
FROM table2
WHERE x = 2
UNION ALL
SELECT id, name
FROM table3
WHERE x = 3
Only one table's data will be returned (if x is any of those values).

Related

Case on union of multiple unions and issue with alias

I have 2 series of unions which I wish to join by another union. In the first one, I have 3 Selects and in the second one I have 2 different Selects.
Select id, min(value)
from table1 t1
join (Select id, value
Union
Select id, value
Union
Select id, value) as foo
on foo.id=t1.id
Group by id
Select id, max(value)
from table1 t1
join (Select id, value
Union
Select id, value) as bar
on bar.id=t1.id
Group by id
I tried to do a union between these two, but it made things pretty complicated. My biggest issue is with my alias. My second is with the case linked to my value columns, which I wish to name value.
Select (alias).id,
Case
When foo.value= 0 or bar.value=1 THEN 1
Else 0
End as value
from table1 t1
Join (Select id, min(value)
from table1 t1
join (Select id, value
Union
Select id, value
Union
Select id, value) as foo
on foo.id=t1.id
Group by id
UNION
Select id, max(value)
from table1 t1
join (Select id, value
Union
Select id, value) as bar
on bar.id=t1.id
Group by id) as (alias)
on ??.id=??.id
I wrote my case the way I think it should be written, but normally, when there are more than one column with the same name, SQL states it as ambiguous. I am still unsure if I should use UNION or INTERSECT, but I assume either of them would be done the same way. How should I deal with this?
I'm reading this right, you probably want something like this
SELECT ...
FROM ( ... union #1 ) AS u1
JOIN (... union #2 ) AS u2 ON u1.id = u2.id

How to create a idendity for each id

Is it possible to create a composite key in sql 2000
code id
abc 1
abc 2
abc 3
def 1
def 2
ghi 1
where the id restarts the count at each change of code. I need the numbering to be exactly like that either by creating a table or other SELECT statement trickery.
how to do this in sql server 2000
Need Query Help
Here is one way to retrieve this data at runtime, without having to actually store it in the table, which is incredibly cumbersome to try and maintain. I'm using a #temp table here but you can pretend #a is your permanent table. As is, this will support up to 256 duplicates. If you need more, it can be adjusted.
CREATE TABLE #a(code VARCHAR(32));
INSERT #a SELECT 'abc'
UNION ALL SELECT 'abc'
UNION ALL SELECT 'abc'
UNION ALL SELECT 'def'
UNION ALL SELECT 'def'
UNION ALL SELECT 'ghi';
GO
SELECT x.code, id = y.number FROM
(
SELECT code, maxid = COUNT(*) FROM #a GROUP BY code
) AS x
CROSS JOIN
(
SELECT DISTINCT number FROM master..spt_values
WHERE number BETWEEN 1 AND 256
) AS y
WHERE x.maxid >= y.number;
DROP TABLE #a;
You can try this
INSERT INTO TABLENAME (code, id) VALUES( 'code',
(Select ISNULL(MAX(id), 0) FROM TableName where code = 'code')+1)

SQL Server Top 1

In Microsoft SQL Server 2005 or above, I would like to get the first row, and if there is no matching row, then return a row with default values.
SELECT TOP 1 ID,Name
FROM TableName
UNION ALL
SELECT 0,''
ORDER BY ID DESC
This works, except that it returns two rows if there is data in the table, and 1 row if not.
I'd like it to always return 1 row.
I think it has something to do with EXISTS, but I'm not sure.
It would be something like:
SELECT TOP 1 * FROM Contact
WHERE EXISTS(select * from contact)
But if not EXISTS, then SELECT 0,''
What happens when the table is very full and you might want to specify which row of your top 1 to get, such as the first name? OMG Ponies' query will return the wrong answer in that case if you just change the ORDER BY clause. His query also costs about 8% more CPU than this modification (though it has equal reads)
SELECT TOP 1 *
FROM (
SELECT TOP 1 ID,Name
FROM TableName
ORDER BY Name
UNION ALL
SELECT 0,''
) X
ORDER BY ID DESC
The difference is that the inner query has a TOP 1 also, and which TOP 1 can be specified there (as shown).
Just for fun, this is another way to do it which performs very closely to the above query (-15ms to +30ms). While it's more complicated than necessary for such a simple query, it demonstrates a technique that I don't see other SQL folks using very often.
SELECT
ID = Coalesce(T.ID, 0),
Name = Coalesce(T.Name, '')
FROM
(SELECT 1) X (Num)
LEFT JOIN (
SELECT TOP 1 ID, Name
FROM TableName
ORDER BY ID DESC
) T ON 1 = 1 -- effective cross join but does not limit rows in the first table
Use:
SELECT TOP 1
x.id,
x.name
FROM (SELECT t.id,
t.name
FROM TABLENAME t
UNION ALL
SELECT 0,
'') x
ORDER BY id DESC
Using a CTE equivalent:
WITH query AS (
SELECT t.id,
t.name
FROM TABLENAME t
UNION ALL
SELECT 0,
'')
SELECT TOP 1
x.id,
x.name
FROM query x
ORDER BY x.id DESC
CREATE TABLE #sample(id INT, data VARCHAR(10))
SELECT TOP 1 id, data INTO #temp FROM #sample
IF ##ROWCOUNT = 0 INSERT INTO #temp VALUES (null, null)
SELECT * FROM #temp
put the top oustide of the UNION query
SELECT TOP 1 * FROM(
SELECT ID,Name
FROM TableName
UNION ALL
SELECT 0,''
) z
ORDER BY ID DESC
IF EXISTS ( SELECT TOP 1 ID, Name FROM TableName )
BEGIN
SELECT TOP 1 ID, Name FROM TableName
END
ELSE
BEGIN
--exists returned no rows
--send a default row
SELECT 0, ''
END

MySQL UNION print every other

How can I make a sql query like the following:
(SELECT `name` FROM table1)
UNION
(SELECT `name` FROM table2)
return each other. Ie. name1 from table1, name1 from table2, name2 from table1, name2 from table2 and so on?
Edit:
Table1
name
Hello
world
Table2
name
guten
tag
The output wanted:
Hello
guten
world
tag
and this should also be possible if adding more unions, so that it takes from the first union, then the second, third, forth and so on.
You could number rows with variables, using 2,4,6,... for the first part of the union and 3,5,7,... for the second:
select #rownum1 := #rownum1+2 as rownum, name
from (select #rownum1:=0) r, table1
union all
select #rownum2 := #rownum2+2 as rownum, name
from (select #rownum2:=1) r, table2
order by rownum;
The select in the from clause (select #rownum2:=1) r is only used to initialize the variable.
Does this work?
set #i = 0;
set #j = 1;
select #i:=#i+2 as rownumber,
name
from table1
union
select #j:=#j+2 as rownumber,
name
from table2
order by rownumber
I read your question as wanting to alternate one row from table1, one from table2 and so on in your results set.
Edit in light of your edit:
Change the "2"s to the number of tables, and add as many variables as you have tables, with consecutive start values in the "set" statements. This will extend in the way you want.
In a similar vein to David M, you can do:
(SELECT #rownum:=#rownum+1 as rownum,`name` FROM table1, (SELECT #rownum:=0) r)
UNION
(SELECT #rownum:=#rownum+1 as rownum,`name` FROM table2, (SELECT #rownum:=0) r)
order by rownum

Getting a distinct value across 2 union sql server tables

I'm trying to get all distinct values across 2 tables using a union.
The idea is to get a count of all unique values in the columnA column without repeats so that I can get a summation of all columns that contain a unique columnA.
This is what I tried (sql server express 2008)
select
count(Distinct ColumnA)
from
(
select Distinct ColumnA as ColumnA from tableX where x = y
union
select Distinct ColumnA as ColumnA from tableY where y=z
)
SELECT COUNT(distinct tmp.ColumnA) FROM ( (SELECT ColumnA FROM TableX WHERE x=y)
UNION (SELECT ColumnA FROM TableY WHERE y=z) ) as tmp
The extra distincts on TableX and TableY aren't necessary; they'll get stripped in the tmp.ColumnA clause. Declaring a temporary table should eliminate the ambiguity that might've prevented your query from executing.
SELECT COUNT(*)
FROM
(
SELECT DISTINCT ColumnA From TableX WHERE x = y
UNION
SELECT DISTINCT ColumnA From TableY WHERE y = z
) t
Using a "UNION" will not return duplicates. If you used "UNION ALL" then duplicate ColumnA values from each table WOULD be return.
To get distinct values in Union query you can try this
Select distinct AUnion.Name,AUnion.Company from (SELECT Name,Company from table1 UNION SELECT Name,Company from table2)AUnion
SELECT DISTINCT Id, Name
FROM TableA
UNION ALL
SELECT DISTINCT Id, Name
FROM TableB
WHERE TableB.Id NOT IN (SELECT Id FROM TableA)