I couldn't find exactly what I'm looking for in another thread.
Let's say I have these two tables:
left:
x
left_y
a
1
a
2
b
4
b
5
right:
x
right_y
a
2
a
3
b
5
b
6
I want to run a query close to this in intention:
SELECT *
FROM left FULL OUTER JOIN right
ON (left.x = right.x AND left.left_y = right.right_y)
OR left.x = right.x
And get an output that has no nulls in x, but maybe has a null in left_y or right_y
x
left_y
right_y
a
1
null
a
2
2
a
null
3
b
4
null
b
5
5
b
null
6
You can use coalesce:
select coalesce(l.x, r.x) as x,
left_y,
right_y
from l full outer join r
on l.x = r.x
and l.left_y = r.right_y
Fiddle
My issue somewhat complex, so I will explain using simplified versions of my tables.
This is Table 1:
Value L AID OID
A 1 1
B 2 1
C 3 1
D 4 1
E 2 1
F 2 2
G 2 3
H 2 4
This is Table 2:
Value R AID OID VAR
Z 0 1 0
Y 1 1 1
X 2 1 1
W 4 1 1
V 0 2 0
U 1 2 1
T 3 2 1
I would like to join these tables such that any row in Table 1 that doesn’t have a corresponding row in Table 2 with both matching AID and OID is returned in a join to the row with a matching OID and an AID and VAR of 0. In this example it would look like this:
Value L Value R AID OID VAR
C Z 3 1 0
F V 2 2 0
H V 4 2 0
I am not certain how to tackle this. Specifically, not sure how to stop the rows that have a matching AID and OID from showing up in my join, and only having the rows that don't have that match. Any advice would be appreciated.
I think you want not exists:
select t1.*
from table1 t1
where not exists (select 1
from table2 t2
where t2.aid = t1.aid and t2.oid = t1.oid and t2.var = 0
);
Name group subgroup
--------------------------
A B C
A B D
A E F
A E G
H I J
H I K
H L M
H L N
into
ID Name ParentID
----------------------
1 A NULL
2 B 1
3 C 2
4 D 2
5 E 1
6 F 5
7 G 5
8 H NULL
9 I 8
10 J 9
11 K 9
12 L 8
13 M 12
14 N 12
INSERT INTO NEWTAB("Name")
SELECT DISTINCT "Name"
FROM TAB;
INSERT INTO NEWTAB("Name", "ParentID")
SELECT DISTINCT C."group", P."ID"
FROM TAB C
LEFT JOIN NEWTAB P
ON C."Name" = P."Name";
INSERT INTO NEWTAB("Name", "ParentID")
SELECT DISTINCT C."subgroup", P."ID"
FROM TAB C
LEFT JOIN NEWTAB P
ON C."group" = P."Name";
I have tables like that: (C1-C2 varchar(10), C3-Number int)
WaitingData
C1 C2 C3 Number
A B 1 10
A B 2 0
A B 3 4
X B 4 2
CompletedData
C1 C2 C3 Number
A B 1 5
A B 2 2
A B 3 0
X B 4 12
I am using the query below to represent the data:
Select wd.C1,wd.C2,wd.C3,wd.Number as NW,cdd.Number as NC
into #AllData
from (Select C1,C2,C3,sum(Number) from WaitingData group by C1,C2,C3) wd
outer apply (Select C1,C2,C3,sum(Number)
from CompletedData cd
where wd.C1=cd.C1 and wd.C2=cd.C2 and wd.C3=cd.C3
) cdd
Select * from #AllData
union
Select C1='Total',C2='Total',C3=-1, sum(NW),sum(NW)
from #AllData
This is giving me an output like:
C1 C2 C3 NW NC
A B 1 10 5
A B 2 0 2
A B 3 4 0
X B 4 2 12
Total Total -1 16 19
However, I want to hide the rows that has no NW but calculate its regarding values while calculating the Total row (see NC below). The output I want is like:
C1 C2 C3 NW NC
A B 1 10 5
A B 3 4 0
X B 4 2 12
Total Total -1 16 19
I could not find a way to provide an output like this. Any help would be so appreciated!
------------------------------EDIT---------------------------------------
------------------------------EDIT---------------------------------------
When I have data in the tables like below, the outer apply is not working like I want, it does not include the data A B 2.
WaitingData
C1 C2 C3 Number
A B 1 10
A B 3 4
X B 4 2
CompletedData
C1 C2 C3 Number
A B 1 5
A B 2 2
X B 4 12
And the output would be like:
C1 C2 C3 NW NC
A B 1 10 5
A B 3 4 NULL
X B 4 2 12
Total Total -1 16 17
In this situation, what can I do to count "2" NC value having by A B 2 on the final result and see NC as 19 instead 17, except inserting all the records that included by CompletedData but WaitingData? (need an efficient way)
Wrap the final result with one more select and exclude rows where NW = 0.
select * from
(
Select * from #AllData
union
Select C1='Total',C2='Total',C3=-1, sum(NW),sum(NC)
from #AllData
) t
where NW <> 0
Edit: Using a full join to get all values from both tables.
with t as
(select coalesce(w.c1,c.c1) as c1,coalesce(w.c2,c.c2) as c2,coalesce(w.c3,c.c3) as c3
, coalesce(w.number,0) as nw , coalesce(c.number,0) as nc
from waitingdata w
full join completeddata c on w.c1 = c.c1 and w.c2=c.c2 and w.c3=c.c3)
select * from
(select * from t
union all
Select C1='Total',C2='Total',C3=-1, sum(NW),sum(NC)
from t) x where nw <> 0
You can do all of this in one query, without temporary tables, intermediate results, subqueries, or UNION by using the ROLLUP operator:
SELECT
WD.C1,
WD.C2,
WD.C3,
SUM(WD.Number) AS NW,
SUM(CD.Number) AS NC
FROM
dbo.WaitingData WD
LEFT OUTER JOIN CompletedData CD ON
CD.C1 = WD.C1 AND
CD.C2 = WD.C2 AND
CD.C3 = WD.C3
GROUP BY
WD.C1,
WD.C2,
WD.C3
WITH ROLLUP
HAVING
GROUPING_ID(WD.C1, WD.C2, WD.C3) IN (0, 7) AND
SUM(WD.Number) <> 0
I've been struggling with this one for a while.
[sample table]
ITEM GROUP
---- -----
4 A
7 A
3 A
8 A
7 B
6 B
9 B
0 C
4 C
2 C
5 C
4 C
7 C
5 D
9 D
2 E
7 E
1 E
4 E
7 F
3 F
9 F
6 F
8 G
4 H
5 H
3 H
9 H
0 H
8 H
I need an sql query that will tell me how many times each "ITEM", on a range of SELECT DISTINCT ITEM appeared with one another in a particular group.
IE:
Items 4 and 8 appeared 2 times (groups A and H).
Items 0 and 4 appeared 2 times (groups C and H).
Items 7, 6 and 9 appeared appeared 2 times (groups B and F).
..And do on. It's ok to ignore "rogue" items that only appear in one group.
Can it be done? Thanks
This will work for pairs of items:
SELECT T1.item, T2.item, COUNT(*)
FROM yourTable T1
JOIN yourTable T2
ON T1.item < T2.item
AND T1.group = T2.group
GROUP BY T1.item, T2.item