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
Related
I have 3 tables:
table: a
id name
2 A
3 B
table: b
id a b
3 2 Asd Ter Gsdt
4 2 Gsd Gsdt Gsda
5 2 Asd Gsd
6 3 Uty Kggs
7 3 Tyud Hffddf
table: c
id a b
6 3 d
7 3 a
8 3 g
9 3 h
10 4 j
11 5 y
12 5 s
13 6 d
14 6 h
expected output:
a b c d
A 2019-04-06 3 a
B 2019-04-06 6 b
I am unsure how to proceed from this, how?
This query do the job, but there is always a question about speed and performance.
select a.name,
(select c_date from c
join b on (c.b_id = b.id)
where b.a = a.id order by c_date desc limit 1) last_c_date,
popular.b_id,
(select photos->0 from b where id = popular.b_id) photo
from a
join (
select distinct on (a)
b.id b_id, a from b
join c on (b.id = c.b_id)
group by b.id, a
order by a, count(*) desc, b.id
) popular on (popular.a = a.id)
order by a.name
If there will be 2 equaly popular b objects in a region, query takes this with smaller id.
If it will be no b object with entries in c than subquery for photo can be surrounded with coalesce (but now it should work too with null value).
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 want to output all the possible combination in two tables without using cartesian join or cross join. Is this possible?
I want to output all the possible combination in two tables without using cartesian join or cross join. Is this possible?
By a strict definition level, it is not possible. Why? Because the definition of a Cartesian product is exactly what you describe (the term "Cartesian join" is not often used but is a synonym for "Cartesian product"). Hence, any method that you use is implementing this functionality. Normally this functionality is implementing using CROSS JOIN (and I reluctantly admit, sometimes using ,).
You might say "add 1 to a number without doing + 1". Someone else comes along and says "use + 2 - 1". Well, that is adding one, but just using two operations rather than one.
If you want a Cartesian product but you don't want to use the CROSS JOIN operator, the most typical method uses ON 1=1:
select t1.*, t2.*
from t1 join
t2
on 1 = 1;
All possible combinations is the definition of a cartesian product.
Here are 3 alternatives to get a cartesian product from two tables.
All 3 alternatives eventually boils down to a cross join (and execution plan is the same for all 3):
Create and populate sample tables:
CREATE TABLE t1
(
int_col int
)
CREATE TABLE t2
(
char_col char(1)
)
INSERT INTO t1 VALUES
(1), (2), (3), (4), (5), (6), (7), (8), (9), (10)
INSERT INTO t2 VALUES
('a'), ('b'), ('c'), ('d'), ('e'), ('f'), ('h'), ('i'), ('j'), ('k')
The queries:
An implicit cross join:
SELECT *
FROM t1, t2
An explicit cross join:
SELECT *
FROM t1
CROSS JOIN t2
Cross apply:
SELECT *
FROM t1
CROSS APPLY t2
All results are the same:
int_col char_col
1 a
2 a
3 a
4 a
5 a
6 a
7 a
8 a
9 a
10 a
1 b
2 b
3 b
4 b
5 b
6 b
7 b
8 b
9 b
10 b
1 c
2 c
3 c
4 c
5 c
6 c
7 c
8 c
9 c
10 c
1 d
2 d
3 d
4 d
5 d
6 d
7 d
8 d
9 d
10 d
1 e
2 e
3 e
4 e
5 e
6 e
7 e
8 e
9 e
10 e
1 f
2 f
3 f
4 f
5 f
6 f
7 f
8 f
9 f
10 f
1 h
2 h
3 h
4 h
5 h
6 h
7 h
8 h
9 h
10 h
1 i
2 i
3 i
4 i
5 i
6 i
7 i
8 i
9 i
10 i
1 j
2 j
3 j
4 j
5 j
6 j
7 j
8 j
9 j
10 j
1 k
2 k
3 k
4 k
5 k
6 k
7 k
8 k
9 k
10 k
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 have an example where in a table there is ID,NAme and M_if(managerID). I populated the table in the following manner
Id Name M_id
1 A 2
2 B NUll
3 C 1
4 D 3
5 E 2
Id is employee ID, Name and M_id is manager ID. In above example A's manager is 2(B), B doesn't have manager, C's manager is 1(A) and so on. I need to find out the names of the employees and their managers name. I have written the following query by doing permutations and combinations which gives me proper result but I am not able to comprehend how exactly the query(left join) is working. Please make me explain the concept.
SELECT (e.Name), ee.name FROM test.employee e
left join test.employee ee on ee.Id = e.M_id
order by e.Id;
result i get
A B
B
C A
D C
E B
Please explain me the joint
two instances are there for same table as :
e
Id Name M_id
1 A 2
2 B NUll
3 C 1
4 D 3
5 E 2
ee
Id Name M_id
1 A 2
2 B NUll
3 C 1
4 D 3
5 E 2
according to your join condition on ee.Id = e.M_id
simply first row of instance e will be selected because of left join and e.M_id will get compared to ee.Id and 2nd row will be selected from second instance of same table.
selection of data from both the table is as :
e.Id e.Name e.M_id | ee.Id ee.Name ee.M_id
1 A 2 | 2 B NUll
2 B NUll |
3 C 1 | 1 A 2
4 D 3 | 3 C 1
5 E 2 | 2 B NUll
that is why it is showing
A B