SQL Server Query- How to Prune a table - sql

I have a Table 'L2'
Itemset Itemset2
1 3
2 3
2 5
3 5
I created a [combination in pair of three] for these values in columns in table 'c3'
Itemset Itemset2 itemset3
1 3 5
2 3 5
1 2 3
1 2 5
Like in Apriori I want to prune the table C3.
i.e. Getting this table as output 'C3Prune'
Itemset Itemset2 itemset3
2 3 5
I want to create a SQL Server query for the same, I tried loops but it's not correct.

2 ways are provided in this answer, I want to give another query with using of UNION and EXCEPT:
select *
from C3
where not exists
(
select c3.itemset a, c3.itemset2 b
union
select c3.itemset a, c3.itemset3 b
union
select c3.itemset2 a, c3.itemset3 b
except
select itemset a, itemset2 b from l2
)
Output:
2 3 5
SQLFIDDLE DEMO

Try this:
DECLARE #L2 TABLE ( I1 INT, I2 INT )
DECLARE #C3 TABLE ( I1 INT, I2 INT, I3 INT )
INSERT INTO #L2
VALUES ( 1, 3 ),
( 2, 3 ),
( 2, 5 ),
( 3, 5 )
INSERT INTO #C3
VALUES ( 1, 3, 5 ),
( 2, 3, 5 ),
( 1, 2, 3 ),
( 1, 2, 5 )
--Version 1
SELECT c.*
FROM #C3 c
JOIN #L2 l1 ON c.I1 = l1.I1 AND c.I2 = l1.I2
JOIN #L2 l2 ON c.I1 = l2.I1 AND c.I3 = l2.I2
JOIN #L2 l3 ON c.I2 = l3.I1 AND c.I3 = l3.I2
--Version 2
SELECT * FROM #C3 c
WHERE
EXISTS(SELECT * FROM #L2 WHERE I1 = c.I1 AND I2 = c.I2) AND
EXISTS(SELECT * FROM #L2 WHERE I1 = c.I1 AND I2 = c.I3) AND
EXISTS(SELECT * FROM #L2 WHERE I1 = c.I2 AND I2 = c.I3)
Output:
I1 I2 I3
2 3 5

Related

Repeating rows based on the frequency

I have a table with 2 columns named A and B which is defined as :
A B
c1 2
c2 3
c3 4
The expected output is :
A B
c1 1
c1 2
c2 1
c2 2
c2 3
c3 1
c3 2
c3 3
c3 4
CREATE TABLE #table2
([A] varchar(2), [B] int)
;
INSERT INTO #table2
([A], [B])
VALUES
('c1', 2),
('c2', 3),
('c3', 4)
;WITH nums AS
(SELECT 1 AS value ,a,b from #table2
UNION ALL
SELECT value + 1 AS value ,A,b
FROM nums
WHERE nums.value <B)
SELECT a,value
FROM nums order by a,value
output
a value
c1 1
c1 2
c2 1
c2 2
c2 3
c3 1
c3 2
c3 3
c3 4
Created a Table valued function in which i used Recursive cte to evaluate recurring value of given in put Then Join the table with function using Cross Apply
CREATE FUNCTION [dbo].[udf_GetData] (
#Data INT
)
RETURNS #output TABLE (
Data INT
)
BEGIN
;WITH CTe
AS
(
SELECT 1 As Data
UNION ALL
SELECT Data+1
FROM CTe
WHERE Data < #Data
)
INSERT INTO #output
SELECT Data FROM CTe
RETURN
END
Sample Data and explained How to call function using CROSS APPLY
DECLARE #Data AS TABLE (A VARCHAR(10),B INT)
INSERT INTO #Data
SELECT 'c1', 2 UNION ALL
SELECT 'c2', 3 UNION ALL
SELECT 'c3', 4
SELECT d.A,
(SELECT [dbo].[udf_GetData](d.B)) AS RecData
FROM #Data d
Result
A RecursiveData
----------------
c1 1
c1 2
c2 1
c2 2
c2 3
c3 1
c3 2
c3 3
c3 4
You could try this:
// test data
declare #tbl table(A char(2), B int);
insert into #tbl values
('c1', 2),
('c2', 3),
('c3', 4);
// create CTE with numbers which we will need to join
declare #max int;
select #max = max(B) from #tbl;
;with numbers as (
select 1 n
union all
select n + 1 from numbers
where n < #max
)
// join numbers with your table
select A, n from #tbl t
join numbers n on t.B >= n.n
order by A, n
Say, your table name is test.
WITH r(a, b, repeat) as
(SELECT a, b, 1 from test
union all
select a, b, repeat+1 from r
where r.repeat < r.b)
select * from r
ORDER BY a, repeat;

Cross table query on a single queston

Here's a table
A B C D R
'a' 1 3 1 0
'a' 2 3 1 1
'a' 2 3 1 0
'b' 1 3 1 1
'b' 2 4 3 2
'b' 1 4 3 0
'c' 2 4 3 0
The cross tabulation of R with respect to A is as follows:
A R count
a 0 2
a 1 1
a 2 0
b 0 1
b 1 1
b 2 1
c 0 1
c 1 0
c 2 0
The cross tabulation gives the frequency of R's value depending on A.
What is the sql query for this operation?
I would use CROSS JOIN and LEFT JOIN
select ta.a, tr.r, count(t.a)
from (select distinct a from tab) TA
cross join (select distinct r from tab) TR
left join tab t on t.a = ta.a and t.r = tr.r
group by ta.a, tr.r
Using CROSS JOIN and a conditional sum to achieve the count:
declare #Table table (A char(1), B int, C int, D int, R int)
Insert into #Table values
('a', 1, 3, 1, 0)
, ('a', 2, 3, 1, 1)
, ('a', 2, 3, 1, 0)
, ('b', 1, 3, 1, 1)
, ('b', 2, 4, 3, 2)
, ('b', 1, 4, 3, 0)
, ('c', 2, 4, 3, 0)
select A, x.R, Sum(iif(x.r = t.R, 1, 0))
from #Table t
cross join (Select distinct R from #Table) x
group by A, x.R
order by a, x.R

how to do permutations combined with permutations in sql

I have created a table that does all the 3 letter combinations of the alphabet. See below
ID 1stLetter 2ndLetter 3rdLetter
1 A B C
2 A B D
3 A B E
and so on
I have a second table as follows:
Letter Number
A 0
A 1
B 0
B 1
C 0
D 0
D 1
E 0
E 1
E 2
I have been trying to figure out how to combine the two so that for each row of the first table it is combined with the second table to get all possible combinations. For example, the output should look like:
NEWID ID 1stLetter 2ndLetter 3rdLetter 1stNumber 2ndNumber 3rd Number
1 1 A B C 0 0 0
2 1 A B C 1 0 0
3 1 A B C 0 1 0
4 1 A B C 1 1 0
5 2 A B D 0 0 0
6 2 A B D 0 0 1
7 2 A B D 0 1 0
8 2 A B D 0 0 1
9 2 A B D 1 0 0
10 2 A B D 1 0 1
11 2 A B D 1 1 0
12 2 A B D 1 0 1
13 2 A B D 1 1 1
14 3 A B E and so on
Is this possible? Any help will be greatly appreciated.
Thanks,
J
This should do the trick, hopefully the code is self explanatory, please ask if not:
CREATE TABLE #combo
(
id INT ,
letter1 NVARCHAR(1) ,
letter2 NVARCHAR(1) ,
letter3 NVARCHAR(1)
);
CREATE TABLE #numbers
(
letter NVARCHAR(1) ,
number INT
);
INSERT INTO #combo
( id, letter1, letter2, letter3 )
VALUES ( 1, 'A', 'B', 'C' ),
( 2, 'A', 'B', 'D' ),
( 3, 'A', 'B', 'E' );
INSERT INTO #numbers
( letter, number )
VALUES ( 'A', 0 ),
( 'A', 1 ),
( 'B', 0 ),
( 'B', 1 ),
( 'C', 0 ),
( 'C', 1 ),
( 'D', 0 ),
( 'D', 1 ),
( 'E', 0 ),
( 'E', 1 ),
( 'E', 2 );
SELECT c.* ,
n1.number ,
n2.number ,
n3.number
FROM #combo c
INNER JOIN #numbers n1 ON c.letter1 = n1.letter
INNER JOIN #numbers n2 ON c.letter2 = n2.letter
INNER JOIN #numbers n3 ON c.letter3 = n3.letter
ORDER BY id;
DROP TABLE #combo;
DROP TABLE #numbers;
Jus use CROSS JOIN
SELECT * FROM [data source1] CROSS JOIN [data source2]

Full Outer Join on Incomplete Data (by id variable)

I have two tables (see example data below). I need to keep all of the ID values in table 1 and merge table 1 with table 2 by sequence. The tricky part is that I also have to retain the field value1 from table 1 and value2 from table 2.
table 1 :
ID sequence value1
-------------------------
p1 1 5
p1 2 10
p2 1 15
p2 2 20
table 2 :
sequence value2
-------------------------
1 10
2 20
3 30
4 40
I need the resulting table to appear like so:
ID sequence value1 value2
----------------------------------
p1 1 5 10
p1 2 10 20
p1 3 - 30
p1 4 - 40
p2 1 15 10
p2 2 20 20
p2 3 - 30
p2 4 - 40
I have tried the following sql code, but it doesn't merge the missing values from from value1 field in table 1 and merge it with the values2 field from table 2
select t1.ID, t2.sequence, t1.value1, t2.value2 from
t2 full outer join t1 on t2.sequence=t1.sequence
Any assistance you can provide is greatly appreciated.
You can try something like this:
select coalesce(t1.[id], t3.[id]),
, t2.[sequence]
, t1.[value]
, t2.[value]
from [tbl2] t2
left join [tbl1] t1 on t1.[sequence] = t2.[sequence]
left join (select distinct [id] from [tbl1]) t3 on t1.[id] is null
SQLFiddle
One way with CROSS JOIN and OUTER APPLY:
DECLARE #t1 TABLE(ID CHAR(2), S INT, V1 INT)
DECLARE #t2 TABLE(S INT, V2 INT)
INSERT INTO #t1 VALUES
('p1', 1, 5),
('p1', 2, 10),
('p2', 1, 15),
('p2', 2, 20)
INSERT INTO #t2 VALUES
(1, 10),
(2, 20),
(3, 30),
(4, 40)
SELECT c.ID, t2.S, ca.V1, t2.V2 FROM #t2 t2
CROSS JOIN (SELECT DISTINCT ID FROM #t1) c
OUTER APPLY(SELECT * FROM #t1 t1 WHERE c.ID = t1.ID AND t1.S = t2.S) ca
ORDER BY c.ID, t2.S
Output:
ID S V1 V2
p1 1 5 10
p1 2 10 20
p1 3 NULL 30
p1 4 NULL 40
p2 1 15 10
p2 2 20 20
p2 3 NULL 30
p2 4 NULL 40
Given this schema:
create table #table_1
(
ID varchar(8) not null ,
sequence int not null ,
value int not null ,
primary key clustered ( ID , sequence ) ,
unique nonclustered ( sequence , ID ) ,
)
create table #table_2
(
sequence int not null ,
value int not null ,
primary key clustered ( sequence ) ,
)
go
insert #table_1 values ( 'p1' , 1 , 5 )
insert #table_1 values ( 'p1' , 2 , 5 )
insert #table_1 values ( 'p2' , 1 , 15 )
insert #table_1 values ( 'p2' , 2 , 20 )
insert #table_2 values ( 1 , 10 )
insert #table_2 values ( 2 , 20 )
insert #table_2 values ( 3 , 30 )
insert #table_2 values ( 4 , 40 )
go
This should get you what you want:
select ID = map.ID ,
sequence = map.sequence ,
value1 = t1.value ,
value2 = t2.value
from ( select distinct
t1.ID ,
t2.sequence
from #table_1 t1
cross join #table_2 t2
) map
left join #table_1 t1 on t1.ID = map.ID
and t1.sequence = map.sequence
join #table_2 t2 on t2.sequence = map.sequence
order by map.ID ,
map.sequence
go
Producing:
ID sequence value1 value2
== ======== ====== ======
p1 1 5 10
p1 2 5 20
p1 3 - 30
p1 4 - 40
p2 1 15 10
p2 2 20 20
p2 3 - 30
p2 4 - 40

CTE parent-child showing siblings

I have a CTE-query that displays a tree using recursion. This works great when displaying the whole tree. But I want to pass in ID as a variable and include the siblings for each current node.
Testcode:
DECLARE #TT TABLE
(
ID int,
Name varchar(25),
ParentID int,
SortIndex int
)
INSERT #TT
SELECT 1, 'A', NULL, 1 UNION ALL
SELECT 2, 'B_1', 3, 1 UNION ALL
SELECT 3, 'B', 1, 2 UNION ALL
SELECT 4, 'B_2', 3, 2 UNION ALL
SELECT 5, 'C', 1, 3 UNION ALL
SELECT 6, 'C_2', 5, 2 UNION ALL
SELECT 7, 'A_1', 1, 1 UNION ALL
SELECT 8, 'A_2', 1, 2 UNION ALL
SELECT 9, 'C_1', 5, 1
;WITH CTETree
AS
(
SELECT *, CAST(NULL AS VARCHAR(25)) AS ParentName, 1 AS Lev,
CAST(ROW_NUMBER() OVER(ORDER BY SortIndex) AS VARBINARY(MAX)) AS SortPath
FROM #TT
WHERE ParentID IS NULL
UNION ALL
SELECT F.*, CTETree.Name AS ParentName, Lev + 1,
SortPath + CAST(ROW_NUMBER() OVER(ORDER BY F.SortIndex) AS BINARY(32))
FROM #TT AS F
INNER JOIN CTETree
ON F.ParentID = CTETree.ID
)
SELECT * FROM CTETree
ORDER BY SortPath
/*
DESIRED RESULT:
WHEN ID = 3 PASSED IN:
1 A NULL 1 NULL 1
3 B 1 2 A 2
2 B_1 3 1 B 3
4 B_2 3 2 B 3
5 C 1 3 A 2
WHEN ID = 1 PASSED IN:
1 A NULL 1 NULL 1
3 B 1 2 A 2
5 C 1 3 A 2
WHEN ID = 9 PASSED IN:
1 A NULL 1 NULL 1
3 B 1 2 A 2
5 C 1 3 A 2
9 C_1 5 1 C 3
6 C_2 5 2 C 3
*/
SQL-Fiddle: http://sqlfiddle.com/#!3/d41d8/5526
Only in once I confront a question where disappear A_1 and A_2. Therefore add in exception(in case clause).
If you need this records delete this expression AND f.ID != 7 AND f.ID != 8.
DECLARE #ID int = 3 -- variable wich you want pass
DECLARE #Matched int = (SELECT CASE WHEN ParentID = 1 THEN ID ELSE ParentID END FROM #TT WHERE ID = #ID)
;WITH CTETree
AS
(
SELECT *, CAST(NULL AS VARCHAR(25)) AS ParentName, 1 AS Lev,
CAST(ROW_NUMBER() OVER(ORDER BY SortIndex) AS VARBINARY(MAX)) AS SortPath,
0 AS Matched
FROM #TT
WHERE ParentID IS NULL
UNION ALL
SELECT F.*, cte.Name AS ParentName, cte.Lev + 1,
SortPath + CAST(ROW_NUMBER() OVER(ORDER BY F.SortIndex) AS BINARY(32)),
CASE WHEN (cte.ID = 1 AND f.ID != 7 AND f.ID != 8)
OR (cte.ID = #Matched AND cte.Lev + 1 > 2)
THEN 1 END AS Matched
FROM #TT AS F INNER JOIN CTETree cte
ON F.ParentID = cte.ID
)
SELECT ID, Name, ParentID, SortIndex, ParentName, Lev FROM CTETree
WHERE Matched IS NOT NULL
ORDER BY SortPath
Demo on SQLFiddle