Counting How ID has Same Join Combination? - mysql

I has Join table, and result is like this
IDA IDB QTY
A 3 1
A 4 1
A 5 1
B 3 1
B 4 1
C 3 2
D 3 2
E 3 1
F 4 1
G 3 1
G 4 1
G 5 1
H 3 3
H 4 3
H 5 3
i'm confused how to count the IDA who has same Condition of IDB and QTY together.
So what i want is:
Combination of IDB - QTY
(3-1, 4-1, 5-1) = 2 from IDA (A and G)
(3-1) = 1 from IDA (E)
(3-2) = 2 from IDA (C and D)
So basically i want count of IDA who has same IDB and QTY Combination. What Query should i do? i still don't get how making query for this logic, thank you.
Edit :
What i want is the result in one query, i will not making manually Where condition of IDB-QTY Combination. (so basically the result is not from Where condition)

You can use aggregating with using group_concat() function
select group_concat( ida order by ida ) as grouped_letters, count(*) as count
from
(
select ida, count( idb - qty ) as ct, sum( idb - qty ) as sm
from tab
group by ida
) q
group by ct, sm
order by ida;
+---------------+-----+
|grouped_letters|count|
+---------------+-----+
| B | 1 |
| C,D | 2 |
| E | 1 |
| F | 1 |
| A,G | 2 |
| H | 1 |
+---------------+-----+
Demo

Related

SQL query to insert a new column by adding the values in one column using distinct features

I have table with three columns (a,b,c), i need to create a new column 'd', by using the distinct features of columns a and b.
a b c
1 p 2
1 p 3
2 q 4
1 q 2
2 r 4
2 r 2
1 p 2
I need the answer as below, where d is the sum of the unique column of a and b
a b c d
1 p 2 7
1 p 3 7
2 q 4 4
1 q 2 2
2 r 4 6
2 r 2 6
1 p 2 7
The result of the column d is,
for distinct(a & b),
then, add the values of c.
And then insert the valuesin the column d (matching the distinct values)
You can try to use SUM and group by a and b columns in subquery, then self join
TestDLL
create table t(
a int,
b varchar(5),
c int
);
insert into t values (1,'p',2);
insert into t values (1,'p',3);
insert into t values (2,'q',4);
insert into t values (1,'q',2);
insert into t values (2,'r',4);
insert into t values (2,'r',2);
insert into t values (1,'p',2);
Query
SELECT t1.*,t2.d
FROM T t1 INNER JOIN (
SELECT a,b,SUM(c) d
FROM T
GROUP BY a,b
) t2 on t1.a = t2.a and t1.b=t2.b
[Results]:
| a | b | c | d |
|---|---|---|---|
| 1 | p | 2 | 7 |
| 1 | p | 3 | 7 |
| 2 | q | 4 | 4 |
| 1 | q | 2 | 2 |
| 2 | r | 4 | 6 |
| 2 | r | 2 | 6 |
| 1 | p | 2 | 7 |
sqlfiddle
If the window function for SUM is supported
select a, b, c, sum(c) over (partition by a, b) as d
from yourtable
use case when and create your other column if generated value is constant
select a,b,c, case when a=1 and b='p' then 7
when a=2 and b='q' then 4
when a=2 and b='r' then 6
when a=1 and b='q' then 2 else '' end as d from
your_table
But it seems to me you need group sum of a,b as a 4th column d , so
you can do like below
select t1.a,t1.b,t1.c,t2.d from yourtable t1
inner join
(select a,b ,sum(c) as d from your table group by a,b) as t2
on t1.a=t2.a and t1.b=t2.b

Change sum for all records starting from specific record

I have table:
+-------------+------------+---------+
| Code | Num | Total |
+-------------+------------+---------+
| A | 5 | 10 |
+-------------+------------+---------+
| B | 7 | 17 |
+-------------+------------+---------+
| C | 8 | 25 |
+-------------+------------+---------+
Now if I want to change Num value for record B from 7 to 9 than total for record B should
be 9 and for record C 27. How to write query that will change all sums starting from specific record?
Working fiddle: http://sqlfiddle.com/#!2/41cb1/1/0
create table b as
(Select 'A' as code,5 as num ,10 as total)
UNION
(Select 'B' as code,7 as num ,17 as total)
UNION
(Select 'C' as code,8 as num ,25 as total);
update b set num = 9 where code = 'B';
set #var=5;
Update b
INNER JOIN
(Select code, num, b.total, #var:=#var+num as NewTotal from b order by code) c
on c.Code=B.code
set b.total=NewTotal;
select * from b;

count value for each unique id

I have a table
id value
1 a
2 a
3 b
4 b
5 b
6 c
My id is primary.
I have total 2 a , 3 b and 1 c. So I want to count total repeat value in each primary id which matches on it
I want this format
id value_count
1 2
2 2
3 3
4 3
5 3
6 1
Try this query:
SELECT a.id, b.valueCnt
FROM tableA a
INNER JOIN (SELECT a.value, COUNT(a.value) valueCnt
FROM tableA a GROUP BY a.value) AS B ON a.value = b.value;
Check the SQL FIDDLE DEMO
OUTPUT
| ID | VALUECNT |
|----|----------|
| 1 | 2 |
| 2 | 2 |
| 3 | 3 |
| 4 | 3 |
| 5 | 3 |
| 6 | 1 |
Try This
select id, value_count from tablename as a1
join (select count(*) as value_count, value from tablename group by value) as a2
on a1.value= a2.value
I suggest you use a subselect without any joins:
SELECT
a.id,(SELECT COUNT(*) FROM tableA WHERE value = a.value) as valueCnt
FROM tableA a
Fiddle Demo
You need to use subquery.
SELECT table.id , x.value_count
FROM table
INNER JOIN
(SELECT t1.value, count(t1.id) as value_count
FROM table t1
Group by t1.value
) x on x.value = table.value

how to get sum of two tables linked to a third

would any sql Wizards out there help with with this question:
suppose I have 3 tables:
tbltype tblvalue tblcost
id | type id | val | typeid id | cost| typeid
---------- ------------------ ------------------
1 | aaa 1 | 3 | 1 1 | 5 | 1
2 | bbb 2 | 2 | 1 2 | 3 | 1
3 | 2 | 2 3 | 1 | 2
4 | 1 | 2 4 | 4 | 2
When I run this query:
SELECT t.type, SUM(val), SUM(cost)
FROM
tbltype t
LEFT JOIN tblcost c ON (c.typeid = t.id)
LEFT JOIN tblvalue v ON (v.typeid = t.id)
GROUP BY t.type;
I get the wrong value of
type | SUM(val) | SUM(cost)
---------------------------
aaa | 10 | 16
bbb | 6 | 10
how do I get the right value of:
type | SUM(val) | SUM(cost)
---------------------------
aaa | 5 | 8
bbb | 3 | 5
and why does sql behaves like that?
To see why, take the group and sums out of your query and look at what it's summing:
SELECT t.type, val, cost
FROM
tbltype t
LEFT JOIN tblcost c ON (c.typeid = t.id)
LEFT JOIN tblvalue v ON (v.typeid = t.id)
You'll see you have each possible combination of the rows from tblcost and tblvalue in the output-- this means some of them get counted multiple times when you sum them.
You need to aggregate tblcost and tblvalue separately. You can then join them back onto tbltype. Gavin's answer already shows one way to do that. Another way is:
SELECT t.type, COALESCE(cost, 0) AS cost, COALESCE(val, 0) AS val
FROM tbltype t
LEFT JOIN (SELECT SUM(cost) AS cost, typeid FROM tblcost GROUP BY typeid) tc
ON tc.typeid = t.id
LEFT JOIN (SELECT SUM(val) AS val, typeid FROM tblvalue GROUP BY typeid) tv
ON tv.typeid = t.id
... which may or may not perform differently (and may or may not be better) depending on which database engine you're actually using.
SELECT t.type,
COALESCE((SELECT SUM(v.val) FROM tblvalue AS v WHERE v.typeid = t.id),0) AS val,
COALESCE((SELECT SUM(c.cost) FROM tblcost AS c WHERE c.typeid = t.id),0) AS cost
FROM tbltype AS t;
I think you've got enough answers suggesting how to solve your problem correctly. You've also got #araqnid's answer that helps you to see why you get such results in the end. The only thing that remains for me seems to be to explain the behaviour itself, as per your request.
Basically, the reason behind such behaviour is the fact that the second join is performed not on tbltype and tblvalue, as one might think, but on the result of the join between tbltype and tblcost, on the one hand, and the tblvalue table, on the other. Now, the first join produces duplicates of t.id, because they match the second table more than once:
tbltype tblcost
id type id cost typeid t.id t.type c.id c.cost c.typeid
-- ---- × -- ---- ------ = ---- ------ ---- ------ --------
1 aaa 1 5 1 1 aaa 1 5 1
1 bbb 2 3 1 1 aaa 2 3 1
3 1 2 2 bbb 3 1 2
4 4 2 2 bbb 4 4 2
The second join produces more duplicates, because:
every occurrence of t.id from the first join's result set is getting matched against v.typeid
and
the typeid values in the tblvalue table are duplicated too.
As a result, rows from both tblcost and tblvalue get duplicated in the process:
tblvalue
t.id t.type c.id c.cost c.typeid id val typeid
---- ------ ---- ------ -------- -- --- ------
1 aaa 1 5 1 × 1 3 1 =
1 aaa 2 3 1 2 2 1
2 bbb 3 1 2 3 2 2
2 bbb 4 4 2 4 1 2
t.id t.type c.id c.cost c.typeid v.id v.val v.typeid
---- ------ ---- ------ -------- ---- ----- --------
1 aaa 1 5 1 1 3 1
1 aaa 1 5 1 2 2 1
= 1 aaa 2 3 1 1 3 1
1 aaa 2 3 1 2 2 1
2 bbb 3 1 2 3 2 2
2 bbb 3 1 2 4 1 2
2 bbb 4 4 2 3 2 2
2 bbb 4 4 2 4 1 2
The only way out for you seems to be to aggregate each table separately. That doesn't necessarily imply separate queries, just separate subqueries, as you can now see from the answers.
QUickest solution is to split the query in two
SELECT
`tbltype`.`type`, SUM(val)
FROM
tbltype
LEFT JOIN `tblvalue` ON (`tblvalue`.`typeid` = `tbltype`.`id`)
GROUP BY `tbltype`.`type`;
and
SELECT
`tbltype`.`type`, SUM(cost)
FROM
tbltype
LEFT JOIN `tblcost` ON (`tblcost`.`typeid` = `tbltype`.`id`)
GROUP BY `tbltype`.`type`;
Something like this:
select t1.id, val, cost from (
select t.id, sum(val) as val
from tbltype t
join tblvalue v on t.id = v.typeId
group by t.id
) t1
join (
select t.id, sum(cost) as cost
from tbltype t
inner join tblcost c on t.id = c.typeid
group by t.id
) t2 on t1.id = t2.id
... or if tblcost and tblvalue are related by id:
select t.id, sum(val) as val, sum(cost) as cost
from tbltype t
inner join tblcost c on t.id = c.typeid
inner join tblvalue v on c.id = v.id
group by t.id

mysql join query

I have two tables that I need to join. These are:
art
id | art
--------
1 | A
2 | B
3 | C
4 | D
5 | E
6 | F
7 | G
8 | H
9 | I
and
Sess
artid | sessid
--------------
1 | 1
2 | 1
3 | 1
4 | 1
1 | 2
4 | 2
5 | 2
6 | 2
1 | 3
2 | 3
7 | 3
4 | 3
where Sess.artid is a foregin key to art.id.
From the tables above we can see that there are 3 sessions: A,B,C,D, A,D,E,F and A,B,G,D.
I want to get a ranking of the arts that occur along with art A. Something like:
D=3
B=2
How could I form such a query in mysql or postgres?
You need to join twice the session table to get the article sharing the same session.
Then join one time with article for the filter clause, and another time to get the name of the other article in the other session.
SELECT aSameSession.art, count(*)
FROM art a
INNER JOIN Sess s
ON a.id = s.artid
INNER JOIN Sess sSameArticle
ON sSameArticle.sessid = s.sessid
INNER JOIN art aSameSession
ON sSameArticle.artid = aSameSession.id
WHERE A.art = 'A'
AND aSameSession.art <> 'A'
GROUP BY aSameSession.art
Output :
B 2
C 1
D 3
E 1
F 1
G 1
This version could be a little difficult to understand, so here a version just with the ID of the article, which is much more simple :
SELECT sSameArticle.artid, count(*)
FROM Sess s
INNER JOIN Sess sSameArticle
ON sSameArticle.sessid = s.sessid
WHERE s.artid = 1
AND sSameArticle.artid != 1
GROUP BY sSameArticle.artid
Output :
2 2
3 1
4 3
5 1
6 1
7 1
Adding the name of the article is just cosmetic.
Something like this, perhaps:
select art,count(*)
from sessid
left join art on art.id=artid
where sessid in (select sessid from sess where artid=1)
group by artid;
?
Example of table structure and join queries on PostgreSQL
CREATE TABLE arts (
arts_id serial PRIMARY KEY,
name text NOT NULL
);
CREATE TABLE sessions (
sessions_id integer NOT NULL,
arts_id integer NOT NULL REFERENCES arts
);
SELECT arts.name, count(sessions_id)
FROM arts
JOIN sessions USING (arts_id)
GROUP BY arts.name
ORDER BY count(sessions_id) DESC;
SELECT a.art, count(*) as ranking
FROM art a, sess s
WHERE a.id = s.artid
group by a.art
order by count(*) DESC;
For a statement in ANSI-92 syntax have a look at Konerak's answer.