How to execute SELECT statements in CASE - sql

I have two SELECT queries let's say.
SELECT FullName FROM TableA
SELECT FirstName FROM TableB
I want to execute both statements in CASE or if there is any alternative for this.
If SELECT FullName FROM TableA returns NULL or no row at all, then it should run following query:
SELECT FirstName FROM TableB
I could use two CASE statements here, but there are around 20 columns in each table and that'll make 40 CASE statements eventually making query very lengthy.

SELECT FullName FROM TableA
union
SELECT FirstName FROM TableB
where not exists
(SELECT FullName FROM TableA)
Working Fiddle

I think this is what you are searching for:
IF EXISTS (SELECT 1 FROM TableA)
SELECT FullName AS Name, TableA.Field1 AS FinalField1,
TableA.Field2 AS FinalField2...
FROM TableA
ELSE
SELECT FirstName AS Name, TableB.Field1 AS FinalField1,
TableB.Field2 AS FinalField2...
FROM TableB

Related

How to compare two different tables find out the rest of records

I have two different tables, called tableA and tableB, I want to compare these two tables.
The structures as following:
tableA use following query has 511 records
SELECT count(*)
FROM tableA
WHERE [ID_NAME] = 'a06'
tableB use following query has 507 records
SELECT count(*)
FROM tableB
where [FILENAME] like 'a06%' and [TIME] = '201705'
I wanna to compare these two tables use the common column PNO, I use the following query can find these two tables intersection(507 records):
SELECT count(*)
FROM tableA
WHERE PNO IN (SELECT PNO
FROM tableB
WHERE [FILENAME] like 'a06%' and [TIME] = '201705')
Now, what should I do ? I think use left join can find out the rest of 4 records, but I tried many times it still didn't work, please help me.
You can do that in many ways, and using left join is one of them:
SELECT ta.*
FROM tableA ta
LEFT JOIN
tableB tb
ON ta.[PNO] = tb.[PNO] and
ta.[ID_NAME] = 'a06' and
tb.[FILENAME] like 'a06%' and tb.[TIME] = '201705'
WHERE tb.[PNO] is null
Note that the conditions that were previously in your WHERE clauses are now moved in the join condition; that's because the LEFT JOIN will assign NULL values to the rows that aren't matched, but if you filter on some of the fields of the right table this feature gets lost.
Edit
Another option is following the same path you were using to find the intersection, just adding the condition on tableA and changing IN to NOT IN:
SELECT *
FROM tableA
WHERE PNO NOT IN (
SELECT PNO
FROM tableB
WHERE [FILENAME] like 'a06%' and [TIME] = '201705'
) and
[ID_NAME] = 'a06'
Basically You want to do A-B
SELECT *
FROM tableA t1
WHERE t1.PNO Not IN (SELECT PNO
FROM tableB
WHERE [FILENAME] like 'a06%' and [TIME] = '201705')
OR
SELECT *
FROM tableA t1
WHERE t1.PNO EXCEPT
(SELECT *
FROM tableB
WHERE [FILENAME] like 'a06%' and [TIME] = '201705')
Assuming you are on SQL Server 2008 +
SELECT PNO FROM TABLE A
INTO #TEMP_A
EXCEPT
SELECT PNO FROM TABLE B
Will return the PNO that are not in both tables
SELECT *
FROM tableA
WHERE PNO (Select PNO from #TEMP_A)
Will return all rows in table A with the missing PNO.

merge statement - upsert - performing unique test in source table as well

I need some help with SQL Server merge statement. I am using version 2008.
I have two tables table1 and table2 with 3 column in each table: name, age, lastname.
I want to do little variant of Upsert from table2 to table1. If record exists in table 1, ignore. If doesn't exist then insert.
I know following would work -
merge into [test].[dbo].[table1] a
using [test].[dbo].[table2] b
on a.name = b.name and a.lastname = b.lastname
when not matched then
insert (name, age, lastname) values (b.name, b.age, b.lastname)
I would like to know if I could do something like this? Currently following doesn't work:
merge into [test].[dbo].[table1] a
using [test].[dbo].[table2] b
on a.name = b.name and a.lastname = b.lastname
when not matched then
insert (select name, max(age), lastname from b group by name, lastname)
Basically I want to insert only 'unique records' from table 2 to table 1. Unique means name and lastname should be same.
Thanks.
Its not really an UPSERT operation its a simple insert and I would do something like this....
insert into [test].[dbo].[table1](name, age, lastname)
SELECT b.name, MAX(b.age) Age, b.lastname
FROM [test].[dbo].[table2] b
WHERE NOT EXISTS (SELECT 1
FROM [test].[dbo].[table1]
WHERE name = b.name
and lastname = b.lastname)
GROUP BY b.name, b.lastname
UPSERT would be if you updated records if they already existed.
For just insert you don't really Merge. An insert alone should be enough. But heres a way to do it
merge into [test].[dbo].[table1] a
using (
select
name,
lastname,
max(age) age
from [test].[dbo].[table2]
group by
name,
lastname
) b on
a.name = b.name and
a.lastname = b.lastname
when not matched
then
insert (
name,
lastname,
age
)
VALUES (
b.name,
b.lastname,
b.age
);

SQL Query efficiency (JOIN or Cartesian Product )

Hello I am Confused with three scenarios which commonly every one use in almost every project.
I wanted to Know which one of these will be Efficient accordinng to - Less Time Complexity - Efficiency - effectiveness
TableA (userid ,username, email , phone)
TableB (username,TestField)
.
Case 1
select email, TestField from TableA , TableB
where TableA.username = TableB.username and
TableB.username = 'ABC'
group by email, TestField
Case 2
select email, TestField from TableA
inner join TableB on TableB.username = 'ABC'
Case 3
declare #uname nvarchar(20);
set #uname = 'ABC';
declare #Email nvarchar(20);
select #Email= email from TableA where username = #uname;
select #Email as email , TestField from TableB
where username = #uname
Case 2 will give you a different output anyway, as you are not joining TableA and TableB in any way so you get a Cartesian product.
Since all of a sudden email came up, you will need a join in case 1:
In Case 1 you can simply rewrite the query to
SELECT DISTINCT A.Email , B.TestField
FROM TableA A join TableB B on A.username = B.Username
WHERE B.username = 'ABC'
Which is more readable and easier to maintain as you do not ave a superfluous GROUP BY clause.
In Case 3 you have userId in your where clause, which is not even in your tableB according to your post.
In general, for maintainability and readibility:
Use explicit joins
SELECT * FROM A JOIN B ON A.id = B.id
is preferable over
SELECT * FROM A, B WHERE A.id = B.id
And use DISTINCT when you want distinct values, instead of GROUP BY over all columns:
SELECT DISTINCT a, b, b FROM TABLE
is preferable over
SELECT a, b, c FROM TABLE GROUP BY a, b, c
Most database experts will tell you that cross products are evil and to be avoided. Your first example would work just fine. It is an implicit inner join.
Your second example is syntactically incorrect. I suspect you'd get an error from MSSQL Server Manager. What you probably meant was:
select a.email, b.TestField
from TableA a inner join TableB b
on (b.username = a.username)
where b.username = 'ABC'
Your first example will probably be the more efficient, since MSSQL Server is smart enough to do the projection on TableB.username before doing the join. I'm not so certain that this would be the case in the above version of case 2.
To be sure you could do it like this:
select a.email, b.TestField
from TableA a inner join
(select * from TableB where TableB.username = 'ABC') b
on (b.username = a.username)
where b.username = 'ABC'
Hope that helps.

How to get the result of select statement grouped by a column to perform join statement on it?

How to get the result of select statement grouped by a column to perform join statement on it ?
You should enclose the select statement that contains the GROUP BY instead of one of the joined table, something like this:
SELECT t1.Id, ....
FROM Table1 t1
INNER JOIN
(
SELECT Id, COUNT(*)
FROM Table2
GROUP BY Id
) t2 ON t1.Id = t2.Table1Id
This might help you:
suppose there are two table
1.student
(stud_id pk)
(branch_id fk)
2. branch
(branch_id pk)
(branch name varchar)
(city varchar)
select * from student s,branch b where s.branch_id=b.branch_id group by b.city

Having trouble with this simple SQL Select statement

I have two tables, A and B.
Both have the exact same columns.
I need to select all the items in TableA that ARE NOT in TableB.
This is intersection, right? How can I do this?
assuming TableA and TableB have a primary key of name id.
select TableA.*
from TableA
left outer join TableB on TableB.id = TableA.id
where TableB.id is null;
This will find all entries where table b does not have an instance of table a's id.
You could use the EXISTS clause
SELECT * FROM TableA
WHERE NOT Exists
(
SELECT Column1 FROM TableB
WHERE TableA.Column1 = Table2.Column1
AND TableA.Column2 = Table2.Column2
....
)
Replace .... with the rest of the columns in the two tables.
SELECT ColumnA, ColumnB
FROM TableA
EXCEPT
SELECT ColumnA, ColumnB
FROM TableB
You have your terminology wrong. The intersection would be the rows that are in both Table A and Table B. What you are actually looking for is the relative complement of A and B. To get a relative complement you want to do an antijoin:
SELECT * FROM TableA EXCEPT SELECT * FROM TableB.
or NOT IN
SELECT *
FROM TableA
WHERE TableA.Id NOT IN (SELECT TableB.Id FROM TableB)