recursion in sql server 2005 - sql

i Want to genrate possible combination with particluar no in sql server 2005 recursively.
e.g
we Have Main No 2 and Sub no 4,5,6
Combination are
2 4
2 5
2 6
4 5
4 6
5 6
5 2
...........like combination.
Thank u

declare #T table (Num int)
insert into #T values (2)
insert into #T values (4)
insert into #T values (5)
insert into #T values (6)
select
T1.Num as Num1,
T2.Num as Num2
from #T as T1
cross join #T as T2

Insert the numbers in TempTable and use Cross Join
Create Table #LeftTemp
( ID int,
)
Create Table #RightTemp
( ID int,
)
-- Write insert statements
Select * from #LeftTemp CROSS JOIN #RightTemp

;With
List AS (SELECT 2 AS y UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6)
SELECT
*
FROM
List CROSS JOIN list
You'd generate list from your tables

Related

Using subquery at IN codition in Oracle Pivot

If I don't know in advance what values are at colum name C0,
how to modify my IN condition?
If I use "IN ( 'a' AS A, 'b' AS B )", it works as below.
ROWNUM M A B
------ -- -- --
1 a__ 3.5 35
2 abd 1.5 15
3 abe 3.5 35
4 ace 5.5 55
But, If I use subquery "IN ( SELECT DISTINCT C FROM DATAA)",ORA-00936 error shows.
My code as below;
--Table and data
CREATE TABLE T4 (
C0 VARCHAR2(10),
C1 VARCHAR2(10),
C2 NUMBER
);
INSERT INTO T4 VALUES ('a','abd',1);
INSERT INTO T4 VALUES ('a','abd',2);
INSERT INTO T4 VALUES ('a','abe',3);
INSERT INTO T4 VALUES ('a','abe',4);
INSERT INTO T4 VALUES ('a','ace',5);
INSERT INTO T4 VALUES ('a','ace',6);
INSERT INTO T4 VALUES ('b','abd',10);
INSERT INTO T4 VALUES ('b','abd',20);
INSERT INTO T4 VALUES ('b','abe',30);
INSERT INTO T4 VALUES ('b','abe',40);
INSERT INTO T4 VALUES ('b','ace',50);
INSERT INTO T4 VALUES ('b','ace',60);
--Code
WITH DATAA AS (
SELECT ROWNUM,rr.C0,rr.M, rr.ss
FROM
(
SELECT C0,C1 M, AVG(C2) ss FROM T4 GROUP BY C0, C1
UNION
SELECT C0,SUBSTR(C1,1,1)||'__' ,AVG(C2) ss FROM T4 GROUP BY C0,SUBSTR(C1,1,1) ) rr
)
-- USING PIVOT
SELECT
ROWNUM,
TAB.*
FROM
(
SELECT
*
FROM
(
SELECT
M,
C0,
SS
FROM
DATAA
) PIVOT (
SUM ( SS )
FOR ( C0 )
IN ( 'a' AS A, 'b' AS B ) -- This condition works correctly, as expected
--IN ( SELECT DISTINCT C FROM DATAA) -- But,this subquery does not work. ORA-00936 error shows.
)
ORDER BY
1
) TAB;
You are searching for dynamic PIVOT. One way is to use PIVOT XML:
Adding the XML keyword to the PIVOT operator allows us to convert the generated pivot results to XML format. It also makes the PIVOT a little more flexible, allowing us to replace the hard coded IN clause with a subquery, or the ANY wildcard.
SELECT *
FROM (SELECT M, C0, SS FROM DATAA)
PIVOT XML (SUM(SS) FOR (C0) IN (SELECT DISTINCT C FROM DATAA))

missing number or max number from the list

I am looking for missing number in the list, it works perfectly fine but when it start from 2, would it be possible to get 1. in below insertion
it should provide 1 not 4. please help thanks
drop table #temp
create table #temp
(
Number INT
)
insert into #temp
(Number)
select 2 union all
select 3 union all
select 5
SELECT MIN(t1.Number) + 1 AS MissingNumber
FROM #temp t1
LEFT OUTER JOIN #temp t2 ON (t1.Number + 1 = t2.Number)
WHERE t2.Number IS NULL
I will suggest you to create a separate numbers table to do this.
There a many ways to create number table. Check this link for more info
SELECT TOP (1000) n = Row_number()OVER (ORDER BY number)
INTO #numbers
FROM [master]..spt_values
ORDER BY n;
CREATE TABLE #temp
(Number INT)
INSERT INTO #temp(Number)
SELECT 2
UNION ALL
SELECT 3
UNION ALL
SELECT 5
SELECT Min(t1.n) AS MissingNumber
FROM #numbers t1
LEFT OUTER JOIN #temp t2
ON ( t1.n = t2.Number )
WHERE t2.Number IS NULL
I think its not possible because join doesn't knows that number starts from 1. it will search for min value.
we can use while loop to solve problem
use this
IF OBJECT_ID('Tempdb..#temp') IS NOT NULL
DROP TABLE #temp
CREATE TABLE #temp ( Number INT )
INSERT INTO #temp
( Number )
VALUES ( 2 ),
( 3 ),
( 5 );
WITH cte
AS ( SELECT n = 1
UNION ALL
SELECT n + 1
FROM cte
WHERE n <= 100 --can be increased with OPTION ( MAXRECURSION {iteration value} ) at the end of the query
)
SELECT MIN(cte.n) AS MissingNumber
FROM cte
LEFT JOIN #temp t ON ( cte.n = t.Number )
WHERE t.Number IS NULL

SQL - order by list order

I have the following query that returns rows based on a comma seperated list
Select * from Table where RecordID in (22,15,105,1,65,32)
I would like the results of this query to return to in the order of the ID's in the list. Is that possible with SQL?
Thanks in advance
select * from Table
where RecordID in (22,15,105,1,65,32)
order by (
case RecordID
when 22 then 1
when 15 then 2
when 105 then 3
when 1 then 4
when 65 then 5
when 32 then 6 end)
If you need the output to appear in a particular order, then you need to specify that order, using something the server can sort. Not knowing which engine you're working against, the general scheme would be to create a temp table or use rowset constructors to pair each record ID with its desired sort order.
E.g. (SQL Server)
declare #T table (RecordID int,Position int)
insert into #T (RecordID,Position)
select 22,1 union all
select 15,2 union all
select 105,3 union all
select 1,4 union all
select 65,5 union all
select 32,6
select * from Table t inner join #T t2 on t.RecordID = t2.RecordID order by t2.Position
I'd to the ordering in the client, but if you really want to do it in SQL, do it like this:
declare #T table (id int identity(1,1), RecordID int)
insert into #T (RecordID)
values (22), (15), (105), (1), (65), (32)
select * from
[table] t
inner join #t s on t.id=s.recordid
where t.id in (22, 15, 105, 1, 65, 32)
order by s.id
(works in SQL Server 2008)
Yes. You add the ORDER BY recordedid clause at the end.
The last time I had to do this I ended up doing a union all and generating a select statement for each id, i.e.
select * from Table where RecordID = 22
union all
select * from table where recordid = 15
etc.
It was a pain but it worked.
Use ORDER BY against the RecordID
Select * from Table where RecordID in (22,15,105,1,65,32) ORDER BY RecordID

How to create a view which merges two tables?

I have two tables which have the exact same structure. Both tables can store the same data with different primary keys (autoincremented integers). Therefore, there is a third table which lists which two primary keys list the same data. However, there also exist rows which don't exist in the other. Therefore, a simple join won't work since you will have two rows with the same primary key but different data. Therefore, is there a way of reassigning primary keys to unused values in the view?
Table1
ID name
1 Adam
2 Mark
3 David
4 Jeremy
Table2
ID name
1 Jessica
2 Jeremy
3 David
4 Mark
Table3
T1ID T2ID
2 4
3 3
4 2
I am looking for a result table like the following:
Result
ID name
1 Adam
2 Mark
3 David
4 Jeremy
5 Jessica
The real heart of the question is how i can assign the temporary fake id of 5 to Jessica and not just some random number. The rule I want for the ids is that if the row exists in the first table, then use its own id. Otherwise, use the next id that an insert statement would have generated (the column is on autoincrement).
Answer to edited question
select id, name from table1
union all
select X.offset + row_number() over (order by id), name
from (select MAX(id) offset from table1) X
cross join table2
where not exists (select * from table3 where t2id = table2.id)
The MAX(id) is used to "predict" the next identity that would occur if you merged the data from the 2nd table into the first. If Table3.T2ID exists at all, it means that it is already included in table1.
Using the test data below
create table table1 (id int identity, name varchar(10))
insert table1 select 'Adam' union all
select 'Mark' union all
select 'David' union all
select 'Jeremy'
create table table2 (id int identity, name varchar(10))
insert table2 select 'Jessica' union all
select 'Jeremy' union all
select 'David' union all
select 'Mark'
create table table3 (t1id int, t2id int)
insert table3 select 2,4 union all
select 3,3 union all
select 4,2
Answer to original question below
So the 3rd table is the one you want to build (a view instead of a table)?
select newid=row_number() over (order by pk_id), *
from
(
select a.*
from tblfirst a
UNION ALL
select b.*
from tblsecond b
) X
The data will contain a unique newid value for each record, whether from first or second table. Change pk_id to your primary key column name.
Assuming you have below data, as I understand reading your question:
Table: T1
ID name
--------
1 a
2 b
3 c
Table: T2
ID name
--------
2 b
3 c
4 d
Table: Rel
ID1 ID2
--------
2 2
3 3
T1 has some data which is not in T2 and vice versa.
Following query will give all data unioned
SELECT ROW_NUMBER() OVER (order by name) ID, Col
from
(
SELECT ISNULL(T1.name,'') name
FROM T1 t1 LEFT JOIN Rel TR ON TR.ID1 = T1.ID
union
SELECT ISNULL(T2.name,'') name
FROM T2 t2 LEFT JOIN Rel TR ON TR.ID2 = T2.ID
) T
If I understand you correct, following might work
Select everything from your first table
Select everything from your second table that is not linked to your third table
Combine the results
Test data
DECLARE #Table1 TABLE (ID INTEGER IDENTITY(1, 1), Value VARCHAR(32))
DECLARE #Table2 TABLE (ID INTEGER IDENTITY(1, 1), Value VARCHAR(32))
DECLARE #Table3 TABLE (T1ID INTEGER, T2ID INTEGER)
INSERT INTO #Table1 VALUES ('Adam')
INSERT INTO #Table1 VALUES ('Mark')
INSERT INTO #Table1 VALUES ('David')
INSERT INTO #Table1 VALUES ('Jeremy')
INSERT INTO #Table2 VALUES ('Jessica')
INSERT INTO #Table2 VALUES ('Jeremy')
INSERT INTO #Table2 VALUES ('David')
INSERT INTO #Table2 VALUES ('Mark')
INSERT INTO #Table3 VALUES (2, 4)
INSERT INTO #Table3 VALUES (3, 3)
INSERT INTO #Table3 VALUES (4, 2)
SQL Statement
SELECT ROW_NUMBER() OVER (ORDER BY ID), t1.Value
FROM #Table1 t1
UNION ALL
SELECT ROW_NUMBER() OVER (ORDER BY ID) + offset, t2.Value
FROM #Table2 t2
LEFT OUTER JOIN #Table3 t3 ON t3.T2ID = t2.ID
CROSS APPLY (
SELECT Offset = COUNT(*)
FROM #Table1
) offset
WHERE t3.T2ID IS NULL

select a set of values as a column without CREATE

I'm trying to write a query that will return all QUERY_ID values alongside all matching TABLE_ID values, where QUERY_ID is not specified in any table, and I can't create tables, so have to specify it in the query itself:
QUERY_ID TABLE_ID
1 1
2 NULL
3 3
4 4
5 NULL
I feel like there ought to be a simple way to do this, but I can't think of it for the life of me. Any help would be wonderful. Thanks!
select q.QUERY_ID, t.TABLE_ID
from (
select 1 as QUERY_ID
union all
select 2
union all
select 3
union all
select 4
union all
select 5
) q
left outer join MyTable t on q.QUERY_ID = t.TABLE_ID
one way by using the built in master..spt_values table
SELECT number AS QUERY_ID,TABLE_ID
FROM master..spt_values v
LEFT JOIN YourTable y ON y.QUERY_ID = y.TABLE_ID
WHERE TYPE = 'p'
AND number > 0
AND number <= (SELECT COUNT(*) FROM YourTable)
order by QUERY_ID
are you able to create #temp tables...can you do this?
create table #temp(QUERY_ID int identity,TABLE_ID varchar(200))
insert #temp(TABLE_ID)
select TABLE_ID
from YourTable
select * from #temp
order by QUERY_ID
drop table #temp
or like this
select identity(int,1,1) as QUERY_ID,TABLE_ID
into #temp
from YourTable
select * from #temp
order by QUERY_ID
On sql server 2005 and up there is the row_number function so maybe a reason to upgrade :-)