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

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

Related

SQL Query to sum multiple count union queries

I have a statement with following structure, and I'm trying to sum all the count results.
I have tried using the SUM function outside of the nested count queries combined using the same variable declaration for each of the union, but error says that I must give them separate aliases. However, if I do that, won't I need to refer to these separately within the SUM function?
My SQL Code returning 2 rows:
SELECT COUNT(col_x) FROM tablea
UNION
SELECT COUNT(col_y) FROM tableb;
OUTPUT
64
10
Now when I try to SUM the answers I run into trouble:
WITH total as(
SELECT COUNT(col_x) FROM tablea as rowtotal
UNION
SELECT COUNT(col_y) FROM tableb as rowtotal
) SELECT SUM(rowtotal) from total;
The error is around using the variable 'rowtotal' twice. Surely there's an easier way to this?
I simply want a sum of both values as:
OUTPUT
74
You don't need window functions for that
select sum(cnt) as total
from
(
SELECT COUNT(col_x) as cnt FROM tablea
UNION
SELECT COUNT(col_y) FROM tableb
) tmp
You can use +:
SELECT ( (SELECT COUNT(col_x) FROM tablea) +
(SELECT COUNT(col_y) FROM tableb)
)
Or a cross join:
SELECT a_cnt + b_cnt
FROM (SELECT COUNT(col_x) as a_cnt FROM tablea) a CROSS JOIN
(SELECT COUNT(col_y) as b_cnt FROM tableb) b;
Do not use UNION! It removes duplicates, so your sum may be off. You can use UNION ALL, but you have alternatives.
Try this
WITH total as(
SELECT COUNT(col_x) as rowtotal FROM tablea
UNION
SELECT COUNT(col_y) FROM tableb
) SELECT SUM(rowtotal) from total
You don;t need to give alias on table, instead it is actually saying to provide alias for column name.
WITH total as(
SELECT COUNT(col_x) as total FROM tablea --- it is necessary over here
UNION
SELECT COUNT(col_y) as total FROM tableb --- it is not mandatory to give alias on second statement of UNION
) SELECT SUM(rowtotal) as total from total;

Run a query with out a subquery to yield results

'MotorVehicles' Table
I ran a query to find 'AVG(Price) * 2' of attached table, then I ran another query where I substituted 'AVG(Price) * 2' with a hard number, I was able to get the two records in the result table, I have tried to use the aggregate functions in a 'Having' clause but my result table comes back empty. Need some help I would like to formulate a SELECT statement without a subquery to find all Motor vehicles whos price is more or equal to 'AVG(Price * 2)' in attached table.
thanks in advance
Many methods, this isn't nice, but it would work:
;with cte_a as
(
select avg(Price)*2 [Average]
from yourTable
-- or whatever your query to get average is as long as only 1 result
)
select *
from yourTable yt
inner join cte_a a on 1 = 1
where price >= a.Average
select * from MotorVehicles where price > (select avg(price) from t)*2;
I apologise if this is the subquery you want to avoid.
You can get something similar using a partitioned AVG().
DECLARE #T TABLE
(
X INT
)
INSERT #T SELECT 1
INSERT #T SELECT 10
INSERT #T SELECT 15
INSERT #T SELECT 20
SELECT X,XAVG=AVG(X) OVER(PARTITION BY 1 ) FROM #T
Resulting in:
X XAVG
1 11
10 11
15 11
20 11

multiple select in one query [Teradata]

I'm trying to do multiple select from diff tables and just have a result in one column.
SELECT COUNT(*) FROM tb1 union
SELECT COUNT(*) FROM tb2 union
SELECT COUNT(*) FROM tb3;
output should be like:
593643
18103600
0
Problem with this is that the result is being arranged on desc order.
Like below:
0
593643
18103600
I would want the result to be as I put the select statement.
Please advise. Btw, I'm using teradata.
Thank you.
SQL result sets are inherently unordered, unless you explicitly specify an order by clause. You can do this with a subquery:
select cnt
from ((SELECT COUNT(*) as cnt, 1 as ord FROM tb1)
union all
(SELECT COUNT(*), 2 FROM tb2)
union all
(SELECT COUNT(*), 3 FROM tb3)
) t
order by ord
If you want specific order, add ORDER BY clause. It would also be good to use UNION ALL so you always get 3 rows, even with duplicate results (two tables having the same number of rows):
SELECT 'tbl1' AS tablename, COUNT(*) AS cnt, 1 AS ord FROM tb1 UNION ALL
SELECT 'tbl2', COUNT(*), 2 FROM tb2 UNION ALL
SELECT 'tbl3', COUNT(*), 3 FROM tb3
ORDER BY ord ;

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

How to get Original Rows filtered by a HAVING Condition?

What is the method in T-SQL to select the orginal values limited by a HAVING attribute. For example, if I have
A|B
10|1
11|2
10|3
How would I get all the values of B (Not An Average or some other summary stat), Grouped by A, having a Count (Occurrences of A) greater than or equal two 2?
Actually, you have several options to choose from
1. You could make a subquery out of your original having statement and join it back to your table
SELECT *
FROM YourTable yt
INNER JOIN (
SELECT A
FROM YourTable
GROUP BY
A
HAVING COUNT(*) >= 2
) cnt ON cnt.A = yt.A
2. another equivalent solution would be to use a WITH clause
;WITH cnt AS (
SELECT A
FROM YourTable
GROUP BY
A
HAVING COUNT(*) >= 2
)
SELECT *
FROM YourTable yt
INNER JOIN cnt ON cnt.A = yt.A
3. or you could use an IN statement
SELECT *
FROM YourTable yt
WHERE A IN (SELECT A FROM YourTable GROUP BY A HAVING COUNT(*) >= 2)
A self join will work:
select B
from table
join(
select A
from table
group by 1
having count(1)>1
)s
using(A);
You can use window function (no joins, only one table scan):
select * from (
select *, cnt=count(*) over(partiton by A) from table
) as a
where cnt >= 2