SQL - count without group by? I need to use two ids for a join - sql

I thought I could count a column and add it as a column as I can with a sum but I get an error about having to group by / having. An example of what I want...
Initial table...
Global ID Local ID Name Role
100 1 Andy Manager
100 2 Andy Manager
100 1 John Co-Manager
200 1 Andy Co-Manager
200 2 John Manager
200 2 Mike Manager
I then want to add a column that counts the number of Manager in each group / local pairing...
Global ID Local ID Name Role Manager Count
100 1 Andy Manager 1
100 2 Andy Manager 1
100 1 John Co-Manager 0
200 1 Andy Co-Manager 0
200 2 John Manager 2
200 2 Mike Manager 2
I tried just joining the two tables on the global / local ID and then adding a column for count of the Role. The problem is that I get an error about grouping / having by but I don't want to group anything. I just want to add the column and still have the same number of rows. Any way around this?
FYI - for the last two rows, the last column has 2 because John and Mike are on the same group / local ID

It looks like your definition of a group is a unique combination of [global_id, local_id]. If that is the case you do want to group by those two values, and do a count, where the role is Manager. But because you want other columns from the original table, you must do that count within an inline view, and then join back to the original table, like so:
select t.*, v.mgr_in_grp
from tbl t
left join (select global_id, local_id, count(*) as mgr_in_grp
from tbl
where role = 'Manager'
group by global_id, local_id) v
on t.global_id = v.global_id
and t.local_id = v.local_id
Fiddle: http://sqlfiddle.com/#!2/fb3ace/2/0
Notice that there is a difference on row 3, as compared to your expected output.
John, Co-manager at global_id and local_id 100 and 1, respectively, belongs to a pair that has a manager in that combination (Andy, your first row). So the count appears should be 1.

Related

count different column values after grouping by

Consider this table:
id name department email
1 Alex IT blah#gmail.com
1 Alex IT blah#gmail.com
2 Jay HR jay#gmail.com
2 Jay Marketing zou#gmail.com
If I group byid,name and count I get:
id name count(*)
1 Alex 2
2 Jay 2
With this query:
select id,name,count(*) from tb group by id,name;
However I would like to count only records that diverge from department,email, so as to have:
id name count(*)
1 Alex 0
2 Jay 1
This time the count for the first group 1,Alex is 0 because department,email have the same values (duplicated) , on the other hand 2,Jay is one because department,email has one different value.
If you meant "two different values" for "Jay", you can use distinct:
select id,name,count(*) from (SELECT distinct * FROM tb) group by id,name;
You can use count(*) - 1 to get similar results in your question.

merge two rows into one sql

this is my table schema, total_hours column is the result of a sum function.
Id name client total_hours
1 John company 1 100
1 John company 2 200
2 Jack company 3 350
2 Jack company 2 150
I want to merge the rows with similar ID into one row, looking like this.
Id name client_a total_hours_a client_b total_hours_b
1 John company 1 100 company 2 200
2 Jack company 3 350 company 2 150
I tried to use pivot but this function does not seem to exist in Dbeaver. Here is my query
SELECT
client
,name
,sum(hours) AS total_hours
FROM pojects
GROUP BY client, name;
Thanks in advance if anyone could be of any help.

Distinct SUM in recursive tablix

I need to report the sum of sales by user and include recursive totals. The problem is, each account has 2 account managers, and the account managers can come from different teams. At each parent level, I want return the distinct sum of each relevant account at the group level.
For example:
Name LEVEL AccountNum Sales
James 1 A1 1000
A2 2000
A3 5000
Mike 2 A1 1000
A2 2000
Sally 3 A1 1000
John 3 A1 1000
Mary 3 A2 2000
Matt 2 A2 2000
A3 5000
Andy 3 A2 2000
A3 5000
Bob 3 A3 5000
I want to return the totals only and not show the account details:
Name Sales
James 8000
Mike 3000
Sally 1000
John 1000
Mary 2000
Matt 7000
Andy 7000
Bob 5000
I'm a relative newbie to SSRS, so would massively appreciate any advice on how to achieve the above group totals! Thanks!
I tried using recursive queries in SQL, but the totals only work up to Level 2, because of the cross-team accounts. Using partition by ranking also only works up to Level 2. (e.g.
{row_number() over (partition by AccountNum, TeamLeaderKey ORDER BY AccountNum ASC))}) in order to exclude any with rank > 1. This falls down at level 1 when there are account with account managers from different teams at level 2.
In case anyone else ever comes across this problem, this is how I solved it. I introduced two new fields in my dataset:
IntraTeamRank:
Case When ROW_NUMBER() OVER (PARTITION BY AccountNum, TeamLeaderKey ORDER BY AccountNum ASC) > 1 Then 0 Else 1 End
InterTeamRank:
Case When ROW_NUMBER() OVER (PARTITION BY AccountNum ORDER BY AccountNum ASC) > 1 Then 0 Else 1 End
I have a parameter set up in SSRS to return the max level.
I then used the following expression in SSRS:
IIf( Level() < (Parameters!MaxLevel.Value - 1),
SUM((Fields!InterTeamRank.Value * Fields!Amount.Value), "StaffName", Recursive),
IIf( Level() = (Parameters!MaxLevel.Value - 1),
SUM((Fields!IntraTeamRank.Value * Fields!Amount.Value), "StaffName", Recursive),
SUM(Fields!Amount.Value), "StaffName")
)
)
Maybe not the most elegant solution, but it worked for my purposes. It would break if an account were shared between regions, as opposed to just teams, but it is unlikely in my scenario. I'd still be interested to know if anyone has a more robust solution.

SQL field default "count(another_field) +1"

I need to create a field COUNT whose default value is the automatically generated count of times NAME has appeared in that table till now, as shown in example below. Since i am adding the field to an existing table, i also need to populate existing rows. How best to go about this please?
ID NAME COUNT
1 peter 1
2 jane 1
3 peter 2
4 peter 3
5 frank 1
6 jane 2
7 peter 4
You would do this when you are querying the table, using the ANSI-standard row-number function:
select id, name, row_number() over (partition by name order by id) as seqnum
from t;

Select records distinct in one column in Postgresql database

I got the following records where different people have the same name:
id name category_id birthdate family_id
1 joe 2 2014-05-01 1
2 jack 3 2013-04-01 2
3 joe 2 1964-05-01 1
4 jack 5 1982-05-01 2
5 emma 1 2014-05-01 1
6 joe 3 2003-07-06 3
Now I need a query which results to the following. I want only each name once per family_id. I need all values of each record afterwards including the id. In case the table gets further rows down the road I need them too. So the result should include all values.
id name category_id birthdate family_id
1 joe 2 2014-05-01 1
2 jack 3 2013-04-01 2
5 emma 1 2014-05-01 1
6 joe 3 2003-07-06 3
I tried it with several approaches (GROUP BY, DISTINCT, DISTINCT ON etc.) but none was working out for me.
When I use a GROUP BY clause (GROUP BY name) I get a ERROR: column "deals.id" must appear in the GROUP BY clause or be used in an aggregate function. But when I put id inside the clause I get all records back.
Same with distinct. There I have to choose all fields on which the result set should be distinct. But I need all values of the record. And because of the primary each record is distinct when i include the id.
I tried it with a sub clause which has filtered all distinct names. I used them in a where clause. But I got all values back including (of course) the not distinct name/family_id records.
Has anybody a helping hand for me?
You might not of specified all of the fields in your group by and if you included id, then that would make the rows unique.
Try something like:
SELECT
name, category_id, birthdate, family_id
FROM family
GROUP BY
name, category_id, birthdate, family_id;
It worked with DISTINCT ON.
The following worked quite well:
SELECT DISTINCT ON (table.name, table.family_id) table.* FROM table;
The only thing I have to check is the ordering. But I wanted to share my solution so far.