JOINING 2 QUERIES - sql

I have a query which gives me results based in my where condition (a varchar e.g. 20200227Abc).
I run a union of those query with same query but changing the Where condition to (20200126xyz).
I want if the data is present for both where conditions only then give me the result of first query where (20200227abc).
Please advise.

If I understand your question correctly, you are looking to get the results for Condition 1 only when it satisfies condition 2 as well. You could use exists in this case. Using a sample:
;with cte as
(select 1 as id,'20200227Abc' as val union
select 1 as id,'20200126xyz' as val union
select 2 as id,'20200227Abc' as val)
select *
from cte a
where val='20200227Abc' and
exists (select 1 from cte b where b.val='20200126xyz' and a.id=b.id)
This should give you the desired result.

I think you want not exists:
select t.*
from t
where t.val = '20200227Abc' or
(t.val = '20200126xyz' and
not exists (select 1 from t where t.val = '20200227Abc')
);

Related

SELECT specific ONLY if exists, otherwise return ALL

How can I write WHERE cluase so it returns rows that meet the criteria, if there are no such records it should return all records from a table?
Using UNION ALL:
select t.* from table t where condition
union all
select t.* from table t cross join (select count(*) cnt from table where condition) c
where c.cnt=0
Or (much more efficiently):
select col1, col2, ... colN
from
(
select t.*, sum(case when condition then 1 else 0 end) over() cnt from table
) s
where condition or s.cnt=0
Replace condition with your WHERE condition
One method you could consider in t-sql is to use ##rowcount to determine if you need to return all rows.
The benefit of doing so is you get two separate execution plans, one only optimised for your first exists criteria and would be beneficial if the majority of results are where the exists condition is met.
select <columns>
from <table>
where <condition>
if ##rowcount=0
begin
select <columns>
from <table>
end
One way would be:
SELECT *
FROM Person
WHERE
Name = 'John'
OR NOT EXISTS(SELECT null FROM Person WHERE Name = 'John')
I don't like it, for all those good reasons mentioned in the comments. If I was handed this requirement as part of a system I was creating I'd probably examine the need for the requirement; selecting all rows from a table is seldom useful if it's the sort of table that you query with a criteria: "Dear user, we couldn't find your person named John so here are the other 4.27 billion users in the system, pagination size 100"
that satisfies me enough:
WHERE (
ISNULL(#variable, '') = ''
OR #variable = [Column]
)
Not exactly what I described above but it returns all the records if condition is not met. However in that case condition would be assigning a value to variable.
1st method
Where ( ISNULL(#Param,'')='' OR ColumnName = #Param)
2nd way
WHERE ( ColumnName =CASE WHEN #Param IS NULL THEN ColumnName
ELSE #Param
END)
3rd way
WHERE (#Param ='' OR #Param =ColumnName)
I would recommend a CTE with not exists:
with cte as (
select t.*
from t
where . . .
)
select *
from cte
union all
select *
from t
where not exists (select 1 from cte);

Get a defined row instead of empty result set: SQL Server

I need a query that return rows even if they have no matching data in table. I know that an empty result set will be returned, but as my project necessity, I need to get a row in result set. It is acceptable though that the values are null. Below is my query:
select Demographic_Id, Total from school.Demographic_Profile where Demographic_Id=2
There is no data with Demographic_Id equal to 2. Still I need to get a result like this:
Demographic_Id | Total
2 | NULL
Any suggestions would help a lot!
If you would get exactly one row or zero rows, then a trick is to use aggregation:
select 2 as Demographic_Id, max(Total) as Total
from school.Demographic_Profile
where Demographic_Id = 2;
You could also use an outer join
select v.did As Demographic_Id,
Total
from (values(2)) v(did)
LEFT JOIN school.Demographic_Profile ON Demographic_Id=v.did
You might use a CTE. The CTE will create a derived table. The UNION ALL will append one row, but only in case the query did not return any rows. Otherwise the query will return just as expected:
WITH CTE AS
(
SELECT object_id
,name
FROM sys.objects
WHERE name='non-existent'
)
SELECT * FROM CTE
UNION ALL
SELECT 2,NULL WHERE (SELECT COUNT(*) FROM CTE)=0
For your case try this:
DECLARE #id INT=2
WITH CTE AS
(
select Demographic_Id, Total
from school.Demographic_Profile
where Demographic_Id=#id
)
SELECT * FROM CTE
UNION ALL
SELECT #id,NULL WHERE (SELECT COUNT(*) FROM CTE)=0
select Demographic_Id, Total from
(SELECT 1 as did
UNION ALL
SELECT 2 as did
UNION ALL
SELECT 3 as did) as innerQuery
left outer join school.Demographic_Profile on did = Demographic_Id

Using a value from one query in second query sql

SELECT AS, COUNT(*)
FROM Table1
HAVING COUNT(AS)>1
group BY AS;
This produces the result
AS COUNT
5 2
I then want to use the AS value in another query and only output the end result. Is this possible.i was thinking something like.
SELECT *
FROM
TABLE 2
Where AS =(
SELECT AS, COUNT(*)
FROM Table1
HAVING COUNT(AS)>1
group BY AS;
);
This is called a subquery. To be safe, you would use in instead of = (and as is a bad name for a column, because it is a SQL key word):
SELECT *
FROM TABLE2
WHERE col IN (SELECT col
FROM Table1
GROUP BY col
HAVING COUNT(col) > 1
);
Your first query is also incorrect, because the having clause goes after the group by.
You could use a subquery with the in operator:
SELECT *
FROM table2
WHERE AS IN (SELECT AS
FROM table1
GROUP BY AS
HAVING COUNT(*) > 1)

SELECT on two other queries in Oracle

So, lets say I want to do something like:
SELECT Query1.a,
Query2.b
FROM (
SELECT q as a
FROM somewhere
),
(
SELECT g as b
FROM elsewhere
)
where Query 1 is
(
SELECT q as a
FROM somewhere
)
and Query2 is
(
SELECT g as b
FROM elsewhere
)
So, i want to select from two other select statements.
Query 1 produces a table
a
value1
Query 2 produces a table
b
value 2
And Query 3 (the outer select statement) produces
a b
value 1 value 2
So, essentially, two result tables are combined as columns and not as rows.
Thank you, if you have any hints.
You basically have your solution. You are only missing the names of your queries, so do like this:
SELECT Query1.a,
Query2.b
FROM (
SELECT q as a
FROM somewhere
) Query1,
(
SELECT g as b
FROM elsewhere
) Query2
It's not clear how you need to connect different rows from tables but it can be something like this:
select query1.a,
query2.b
FROM
(select q as a, ROW_NUMBER() OVER (ORDER BY q) as RN from a) Query1
FULL JOIN
(select q as b, ROW_NUMBER() OVER (ORDER BY q) as RN from b) Query2
ON Query1.RN=Query2.RN
SQLFiddle example
Your syntax is a bit off the SQL charts, but in essence ritgh:
It is possible to do a subquery:
select A.field from (select field from a_table) A;
It is essential that you name your query, if you want to use it in the select or where clauses.
And even possible to combine them like regular tables:
select A.field, B.other_field from (select field from table1) A, (select other_field from table2) B;
It is also possible to do al kind of where, grouping and sorting stuff on it, but not needed in your case.
I assume this is what you're looking for:
SELECT query1.a, query2.b
FROM
(SELECT q as a FROM somewhere) query1,
(SELECT g as b FROM elsewhere) query2
Here is a SQLFiddle to test the query

SELECT TOP ... FROM UNION

What is the best way to SELECT TOP N records from UNION of 2 queries?
I can't do
SELECT TOP N ... FROM
(SELECT ... FROM Table1
UNION
SELECT ... FROM Table2)
because both queries return huge results I need every bit of optimization possible and would like to avoid returning everything. For the same reason I cannot insert results into #TEMP table first either.
I can't use SET ROWCOUNT N either because I may need to group results and this command will limit number of grouped rows, and not underlying row selections.
Any other ideas? Thanks!
Use the Top keyword for inner queries also:
SELECT TOP N ... FROM
(SELECT TOP N... FROM Table1
UNION
SELECT TOP N... FROM Table2) as result
You could try the following. It uses a CTE which would give you the results of both queries first and then you would select your TOP N from the CTE.
WITH table_cte (
(
[col1],
[col2],
...
)
AS
(
SELECT *
FROM table1
UNION ALL
SELECT *
FROM table2
)
SELECT TOP 1000 * FROM table_cte