GROUP BY with only first row of sequence of one column? - mysql

at first here is the alpha version of what I want: http://sqlfiddle.com/#!2/45c89/2
However I don't want to count all representative_id, but only this rows with the lowest id, eg:
(`id`, `economy_id`, `representative_id`)
(1, 1, 5), <-this one, lowest id through the same economy_id=1
(2, 1, 6),
(3, 1, 7),
(4, 1, 8),
(5, 1, 3),
(6, 1, 4),
(7, 1, 1),
(8, 1, 2),
(9, 1, 102),
(10, 2, 7), <-this one, lowest id through the same economy_id=2
(11, 2, 8),
(12, 2, 102),
(13, 2, 1),
(14, 2, 2),
(15, 2, 3),
(16, 2, 4),
(17, 3, 3), <-this one, lowest id through the same economy_id=3
(18, 3, 4),
(19, 3, 1),
(20, 3, 2),
(21, 3, 102),
(22, 4, 1), <-this one, lowest id through the same economy_id=4
(23, 4, 2),
(24, 4, 102),
(25, 5, 1), <-this one, lowest id through the same economy_id=5
(26, 5, 2),
(27, 5, 102),
(28, 5, 7),
(29, 6, 1), <-this one, lowest id through the same economy_id=6
The output should be:
representative_id, count()
According to above example:
5, 1
7, 1
3, 1
1, 3
Is it possible only in SQL?

If I'm understanding your question correctly, I think this should work using min in a subquery and joining back to itself:
select s.representative_id, count(*)
from stl_parliament s
join
(
select min(id) minid
from stl_parliament
group by economy_id
) t on s.id = t.minid
group by s.representative_id
Updated Fiddle Demo

SELECT x.representative_id
, COUNT(*) total
FROM stl_parliament x
JOIN
( SELECT economy_id
, MIN(id) min_id
FROM stl_parliament
GROUP
BY economy_id
) y
ON y.economy_id = x.economy_id
AND y.min_id = x.id
GROUP
BY representative_id;
http://sqlfiddle.com/#!2/45c89/34

You question is a bit confusing.
is it what do you want?
http://sqlfiddle.com/#!2/a58c7/19
select count(economy_id), min_rep_id
from
(
SELECT economy_id, min(representative_id) as min_rep_id
from stl_parliament
GROUP BY economy_id
) as x
GROUP BY min_rep_id

A little complex but should work :
select m.col1, m.col2, count(m.col2) from (
select t.economy_id as col1, l.representative_id as col2 from stl_parliament l,
(select economy_id,MIN(id) as minid from stl_parliament GROUP BY economy_id) t
where t.economy_id=l.economy_id and t.minid=l.id) m group by m.col2
Lots of subqueries, I am not so good with joins

Please try the below query.
SELECT a.rep_id,count(a.rep_id)
FROM(Select min(id) as mid,representative_id as rep_id,economy_id
FROM stl_parliament
GROUP BY economy_id) as a
GROUP BY a.rep_id

Related

Balance the values using SQL in PostgreSQL

My Postgresql table looks like,
CREATE TABLE foo(man_id, subgroup, power, grp)
AS VALUES
(1, 'Sub_A', 4, 'Group_A'),
(2, 'Sub_B', -1, 'Group_A'),
(3, 'Sub_A', -1, 'Group_B'),
(4, 'Sub_B', 6, 'Group_B'),
(5, 'Sub_A', 5, 'Group_A'),
(6, 'Sub_B', 1, 'Group_A'),
(7, 'Sub_A', -1, 'Group_B'),
(8, 'Sub_B', 2, 'Group_B'),
(9, 'Sub_C', 2, 'Group_B');
The power calculation works like this:
Total Power of Subgroup Sub_A in the grp Group_A is (4 + 5 ) = 9
Total Power of Subgroup Sub_B in the grp Group_A is ((-1) + 1 ) = 0
Total Power of Subgroup Sub_A in the grp Group_B is ((-1) + (-1) ) = -2
Total Power of Subgroup Sub_B in the grp Group_B is (6 + 2 ) = 8
So the power of Sub_A in the Group_A is not equal to power of Sub_A in the Group_B
So the power of Sub_B in the Group_A is not equal to power of Sub_B in the Group_B
I can query the database and fetch the data where for a same subgroup name total power is not equal across all the other grp names.
SELECT f.*
FROM (
SELECT subgroup
FROM (
SELECT subgroup, grp, sum(power) AS total_power
FROM foo
GROUP BY subgroup, grp
) sub
GROUP BY 1
HAVING min(total_power) <> max(total_power)
) sg
JOIN foo f USING (subgroup);
I also want to make the sum value identical. For a same subgroup name total power should be equal across all the other grp names.
We can fetch the records where sum is not equal from the above query. Then we can find the difference of sum(power) value and add this difference value into the power of any subgroup where power is smaller under that particular grp.
MySQL solution will be accepted as well.
The above query will return this data because for a same subgroup total power is not equal to across grp s,
(1, 'Sub_A', 4, 'Group_A')
(5, 'Sub_A', 5, 'Group_A')
(3, 'Sub_A', -1, 'Group_B')
(7, 'Sub_A', -1, 'Group_B')
(2, 'Sub_B', -1, 'Group_A')
(6, 'Sub_B', 1, 'Group_A')
(4, 'Sub_B', 6, 'Group_B')
(8, 'Sub_B', 2, 'Group_B')
Now, I want to modify the values of power to make the sum identical,
As an example, for Sub_A total power difference between Group_A and Group_B is (9-(-1-1)) = 11 , So we will add 11 into any of the Sub_A power value under Group_B, let's say we modify this record ,
(3, 'Sub_A', -1, 'Group_B') converted to (3, 'Sub_A', 10, 'Group_B')
The same thing we will do for others also, wherever there is an unbalanced.
Below query will produce the desired result
with foo(man_id, subgroup, power, grp) as (
select * from
(
VALUES
(1, 'Sub_A', 4, 'Group_A'),
(2, 'Sub_B', -1, 'Group_A'),
(3, 'Sub_A', -1, 'Group_B'),
(4, 'Sub_B', 6, 'Group_B'),
(5, 'Sub_A', 5, 'Group_A'),
(6, 'Sub_B', 1, 'Group_A'),
(7, 'Sub_A', -1, 'Group_B'),
(8, 'Sub_B', 2, 'Group_B'),
(9, 'Sub_C', 2, 'Group_B')
) as x(man_id, subgroup, power, grp)
), sub_per_group as (
select
subgroup,
grp,
sum(power) tot_per_grp
from foo
group by subgroup,grp
), sub_calc as (
select
subgroup,
max(tot_per_grp) as max,
json_agg(
json_build_object(
'grp',grp,
'tot_per_grp',tot_per_grp
)
) as grps_tot
from sub_per_group
group by subgroup
having count(distinct tot_per_grp)!=1
)
select f.man_id,f.subgroup,
case
when rn=1 then
(
power+
(
coalesce(max,0)-
coalesce((
select (v->>'tot_per_grp')::int
from
json_array_elements(grps_tot) as v where (v->>'grp')::text =f.grp),0)
)
)
else
power
end,
f.grp
from sub_calc sc
right join (
select
row_number() over(partition by subgroup,grp) as rn,
foo.*
from foo
) f on f.subgroup=sc.subgroup and f.rn=1
order by subgroup,grp

SQL - adding total by searching for another value relating to the amount

been given this problem to solve
Write a function to get the payment sales figures from any given shop. The shop should be searched for by name.
i have this so far
SELECT shopname SUM ( amount ) AS sales
FROM frs_Shop, frs_Payment
WHERE shopname = "shop name"
i have the amount to add up but when i go to compile it adds up every amount in this table
INSERT INTO frs_Payment
(payid, amount, paydatetime, empnin, custid, pstatusid, ptid)
values
(101, "3.99", "2015-10-26 16:26:15", "NIN001", 1, 1, 1),
(95, "15.96", "2015-09-24 16:26:15", "NIN001", 1, 1, 1),
(102, "3.99", "2015-10-11 13:25:31", "NIN003", 2, 1, 1),
(11, "11.97", "2015-06-12 19:37:59", "NIN010", 3, 1, 1),
(7, "11.97", "2015-04-11 12:41:28", "NIN010", 3, 2, 4),
(8, "7.98", "2015-05-05 22:49:02", "NIN010", 3, 1, 1),
(32, "15.96", "2015-07-19 02:26:49", "NIN024", 5, 2, 4),
(83, "7.98", "2015-08-20 16:21:08", "NIN011", 5, 2, 4),
(6, "15.96", "2015-03-04 10:51:03", "NIN027", 6, 2, 4),
(17, "3.99", "2015-10-03 01:06:15", "NIN028", 6, 1, 1),
(39, "11.97", "2015-03-24 20:03:05", "NIN027", 6, 1, 1),
(103, "3.99", "2015-10-27 14:45:11", "NIN009", 7, 1, 1),
(62, "15.96", "2015-10-12 14:23:23", "NIN001", 8, 1, 1),
i want it to only add up the ones i specify with the empnin
You can use an explicit join, and a GROUP BY. I made an assumption on the primary/foreign key relationship between frs_Shop and frs_Payment.
SELECT s.shopname
, p.empnin
, SUM ( p.amount ) AS sales
FROM frs_Shop s
INNER JOIN frs_Payment p on s.empnin = p.empnin
WHERE s.shopname = "shop name"
GROUP BY s.shopname, p.empnin

MySQL query to limit maximums and minimums

I have the following table:
INSERT INTO `test_table` (`id`, `x`, `y`) VALUES (1, 0, 10), (2, 6, 10),
(3, 9, 10), (4, 2, 9), (5, 4, 9), (6, 3, 8), (7, 7, 8), (8, 9, 8),
(9, 0, 7), (10, 2, 7), (11, 5, 7), (12, 10, 7), (13, 2, 6), (14, 7, 6),
(15, 0, 5), (16, 4, 5), (17, 9, 5), (18, 1, 4), (19, 3, 4), (20, 5, 4),
(21, 10, 4), (22, 8, 3), (23, 3, 2), (24, 6, 2), (25, 2, 1), (26, 8, 1),
(27, 0, 0), (28, 5, 0), (29, 6, 0), (30, 10, 0);
and it represent the following picture:
The numbers in the red or pink cells represent the "id" and the coordinates for those cells are "x" and "y".
All I have to do is to come up with a query to show all the cells (only the red ones), excluding the 10 cell within the gray square.
So far I have this:
SELECT * FROM `test_table` WHERE
x between 0 and 10 and
x not between 2 and 8 and
y between 0 and 10 and
y not between 2 and 7
order by id ASC
LIMIT 30
Imagining that the grid goes bellow 0 and beyond 10 in both directions (not showing in the picture); the query must have way too many limits. Anyways, the output is not what I want because it only give me the cells in the corners (the ones within the green areas): 1, 3, 8, 27 and 30
another approach will be to subtract this query:
SELECT * FROM `test_table` WHERE
x between 2 and 8 and
y between 2 and 7
order by id ASC
LIMIT 30
from this one:
SELECT * FROM `test_table` WHERE
x between 0 and 10 and
y between 0 and 10
order by id ASC
LIMIT 30
...but once again; i am unable to do it :(
It just needs to exclude x[2:8],y[2,7].
Try this:
SELECT * FROM `test_table`
WHERE NOT(x between 2 and 8 AND y between 2 and 7);
Just to add the other "side" limits; the final query was implemented like this:
SELECT * FROM
`test_table` WHERE
x between 0 and 10 and
y between 0 and 10 and
not
(x between 2 and 8 and
y between 2 and 7)

mysql consult in same table

i have this table
INSERT INTO `relationships` (`id`, `term_id`, `order`) VALUES
(1, 1, 0),
(4, 2, 0),
(4, 3, 0),
(4, 4, 0),
(4, 5, 0),
(4, 7, 0),
(4, 8, 0),
(6, 3, 0),
(6, 8, 0),
(6, 9, 0),
(8, 6, 0),
(8, 7, 0),
(8, 8, 0),
(8, 10, 0),
(15, 3, 0),
(15, 4, 0),
(15, 10, 0);
I need to select all term_id containing the number 8 and 5 (relationship between this numbers)
expected result = id 4 and id 8
I try this
SELECT `id` FROM `relationships` WHERE `term_id`=8 or `term_id`=5
but selects all term_id belong to 8 and 5
result = id 4 id 8 AND id --> 6 <-- This is not the result I want.
This does the job:
SELECT
id
FROM relationships a
WHERE
a.term_id = 5 AND
EXISTS (SELECT * FROM relationships b WHERE b.term_id = 8 AND b.id = a.id) > 0
demo: http://www.sqlfiddle.com/#!9/e78cc/4/0

Mysql Match and count in the same table

I'm having an trouble with count product with some conditions on the same table..
Table structure:
INSERT INTO `filter` (`filter_seq_id`, `group_id`, `product_seq_id`) VALUES
(1, 1, 10),
(2, 1, 11),
(3, 1, 12),
(4, 1, 13),
(5, 2, 14),
(6, 2, 15),
(7, 2, 16),
(8, 2, 17),
(9, 3, 18),
(10, 3, 19),
(11, 3, 20),
(12, 3, 21),
(13, 4, 20),
(14, 4, 11),
(15, 4, 27),
(16, 4, 29),
(17, 5, 11),
(18, 5, 20),
(19, 5, 27),
(20, 5, 13);
Here i want count distinct product_seq_id for the group_id (1,2,3) only if product_seq_id also exits in both (4,5) group id..
for example:
group_id -> 1 found product_seq_id 11 in 4,5 so distinct count is 1
group_id -> 2 found nothing
group_id -> 3 found product_seq_id 20 in 4,5 so distinct count is 1
i have tried below query its not returning has i expect
its counting if product_seq_id exists in any one of (4,5)
And i want to count only if product_seq_id exits on both "4" and "5" group_id
SELECT
`f`.`group_id`, count(distinct f.product_seq_id) as count
FROM
filter f
JOIN
filter ff ON `ff`.`product_seq_id` = `f`.`product_seq_id`
AND `f`.`group_id` IN (1,2,3)
AND `ff`.`group_id` IN (4,5)
GROUP BY `f`.`group_id`
http://sqlfiddle.com/#!2/996c1/1
Is this what you are looking for?
select f123.GROUP_ID, count(f123.PRODUCT_SEQ_ID)
from (select product_seq_id from filter where group_id=4) f4
inner join (select product_seq_id from filter where group_id=5) f5
on f4.product_seq_id = f5.product_seq_id
inner join (select group_id, product_seq_id from filter where group_id<4) f123
on f123.product_seq_id = f5.product_seq_id
group by GROUP_ID order by GROUP_ID
The first two subselects selects all of the product_seq_id which are in filter in the group 4 or 5. Those 2 list are joined together only if both contain the same product_seq_id.
The Result of this is all the product_seq_id which are both in group 4 and group 5 (in this example 11 and 20)
Next this result is joined with the last subselect, which selects all group_id and product_seq_id in the groups 1 to 3. They are only joined if they contain any product_seq_id, which is in the previous result of the other join (so if they contain the product_seq_id 11 or 20). The Result of this looks like this:
Group_ID, Product_Seq_ID
1 11
3 20
This result is then grouped by the Group_ID and the amount of product_seq_id in each group is counted
EDIT: Added Explanation