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
Related
I am trying to write a sql statement that works something like a store. I have two queries and I want n records from the first query, but if there is less than n, I want the rest from the second.
I tried using TOP n and UNION
SELECT TOP 20 FROM (
(SELECT * FROM t1)
UNION
(SELECT * FROM t2))
but the results are from both tables regardless of how many are in t1. Basically, I want the first query to have precedence. If 5 records exist there and I want them and I want the rest from t2.
Add a column that identifies the query, so the first one have precedence.
SELECT TOP 20 *
FROM ((SELECT 1 as query, * FROM t1)
UNION
(SELECT 2 as query, * FROM t2))
ORDER BY query
you can use a CTE to place a sort order on the two tables and then use that in an order by clause
declare #foo1 table(
bar INT
)
insert into #foo1
values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)
--,(11),(12),(13),(14),(15),(16),(17),(18),(19),(20)
declare #foo2 table(
bar INT
)
insert into #foo2
values (101),(102),(103),(104),(105),(106),(107),(108),(109),(110),(111),(112),(113),(114),(115),(116),(117),(118),(119),(120)
;with base_data as (
select
0 as sort,
f1.bar
FROM #foo1 f1
UNION
SELECT
1 as sort,
f2.bar
FROM #foo2 f2
)
select top 20 bar
from base_data
order by sort, bar
So this is fairly common knowledge to select rows from multiple tables and stack the results on top of each other:
SELECT * FROM table1
UNION
SELECT * FROM table2
UNION
...
However, if I want only a limited number of rows from each table, then how should I write it?
SELECT * FROM table1 LIMIT 2
UNION
SELECT * FROM table2 LIMIT 2
UNION
...
Clearly doesn't work.
Note that in my case, I have 51 tables, all with the same exact columns.
could be work this way
( SELECT * FROM table1 LIMIT 2 )
UNION
( SELECT * FROM table2 LIMIT 2 )
UNION
...
I need to return the unique records between two tables. Ideally, an UNION would solve my problem but both tables contain an object field which gives me an error(cannot ORDER objects without MAP or ORDER method) when I do UNION/distinct.
So, I was wondering if I can do a UNION ALL(to avoid the error) to get all the records first then do something to return only the unique records from there. I tried analytic function combined with the UNION ALL query but no luck so far.
Select * from Table1
union all
Select * from table2
Any help? Note:I need to return all fields.
I actually solved the problem using analytic function+row_num. The query will choose the first record for each set of duplicates hence returning only the unique records.
select * from
(
select ua.*,row_number() over (partition by p_id order by p_id ) row_num from
(
select * from table1
union all
select * from table2
)ua
) inner
where inner.row_num=1
How about this :
SELECT DISTINCT A.* FROM
(
Select * from Table1
union all
Select * from table2
) A;
(or)
SELECT col1,col2,col3...coln FROM
(
Select col1,col2,col3...coln from Table1
union all
Select col1,col2,col3...coln from table2
) A
GROUP BY A.col1,col2,col3...coln;
UNION ALL will give duplicate values as well .. instead use UNION and see if you are facing the error
I have these following SQL codes to do clean-up tasks:
SELECT the first n-rows from the table that satisfies a condition and put them in a new table. Note that the [source].var='1' varies for different tables.
SELECT TOP n * INTO tablen
FROM source
WHERE [source].var='1';
# concrete example
SELECT TOP n * INTO table1
FROM source
WHERE [source].var1='1';
SELECT TOP n * INTO table2
FROM source
WHERE [source].var2='1';
SELECT TOP n * INTO table3
FROM source
WHERE [source].var3='1';
SELECT TOP n * INTO table4
FROM source
WHERE [source].var4='1';
SELECT TOP n * INTO table5
FROM source
WHERE [source].var5='1';
After making n-tables from the first step, I concatenate them using a query.
# code2
SELECT * FROM table1
UNION ALL
SELECT * FROM table2
UNION ALL
SELECT * FROM table3
UNION ALL
SELECT * FROM table4
UNION ALL
SELECT * FROM table5
Finally I put the results of number two into a new table so I can use it.
SELECT *
INTO dest
FROM code2
Does anyone know how to put these set of tedious tasks into one SQL query so that I don't have to repeat 15 times?
Ill try to answer this, but this is my first answer so go easy on me. First I'm not sure if the source table is the same for each "TOP" row query. If it is then you dont need tables, 1-5. Unless of course you want the 5 temp tables for some reason...and I assume you know what you're doing with UNION ALL.
Just query the original table inline:
select a.* into dest
from (select TOP n *
from source
where source.var1='1'
UNION ALL
select TOP n *
from source
where source.var2='1'
UNION ALL
select TOP n *
from source
where source.var3='1'
UNION ALL
select TOP n *
from source
where source.var4='1'
UNION ALL
select TOP n *
from source
where source.var5='1'
) a
I need to count rows in more than one table in SQL Server 2008. I do this:
select count(*) from (select * from tbl1 union all select * from tbl2)
But it gives me an error of incorrect syntax near ). Why?
PS. The actual number of tables can be more than 2.
In case you have different number of columns in your tables try this way
SELECT count(*)
FROM (
SELECT NULL as columnName
FROM tbl1
UNION ALL
SELECT NULL
FROM tbl2
) T
try this:
You have to give a name to your derived table
select count(*) from
(select * from tbl1 union all select * from tbl2)a
I think you have to alias the SELECT in the FROM clause:
select count(*)
from
(
select * from tbl1
union all
select * from tbl2
) AS SUB
You also need to ensure that the * in both tables tbl1 and tbl2 return exactly the same number of columns and they have to be matched in their type.
I don't like doing the union before doing the count. It gives the SQL optimizer an opportunithy to choose to do more work.
AlexK's (deleted) solution is fine. You could also do:
select (select count(*) from tbl1) + (select count(*) from tbl2) as cnt