Encapsulated Group by or conditional aggregation in Vertica DB - sql

I have the following table in a Vertica DB:
+---------+-------+
| Readout | Event |
+---------+-------+
| 1 | A |
| 1 | B |
| 1 | A |
| 2 | B |
| 2 | A |
+---------+-------+
I would like to group each readout and count the frequency of the events, resulting in a table like this:
+---------+----------------+----------------+-----------------+
| Readout | Count(Readout) | Count(Event A) | Count (Event B) |
+---------+----------------+----------------+-----------------+
| 1 | 3 | 2 | 1 |
| 2 | 2 | 1 | 1 |
+---------+----------------+----------------+-----------------+
I am sure there is an easy GROUP BY command, but I can't wrap my head around it.

You want conditional aggregation:
select readout, count(*),
sum(case when event = 'A' then 1 else 0 end) as num_a,
sum(case when event = 'B' then 1 else 0 end) as num_b
from t
group by readout;

Related

Create New Columns from Row Values then Group By

My current table looks like this:
+-------+------+
| Level | Team |
+-------+------+
| 1 | 1 |
| 2 | 1 |
| 2 | 1 |
| 3 | 2 |
| 3 | 2 |
| 3 | 2 |
+-------+------+
I want to group by level and know the count of level for both teams. I can easily get the count of a single team by using the following:
SELECT Level, Count(Team)
FROM table
WHERE Team = 1
GROUP BY Level
SORT BY Level;
+-------+-------------+
| Level | Team1_Count |
+-------+-------------+
| 1 | 1 |
| 2 | 2 |
| 3 | 0 |
+-------+-------------+
However, the end result I want is below:
+-------+-------------+-------------+
| Level | Team1_Count | Team2_Count |
+-------+-------------+-------------+
| 1 | 1 | 0 |
| 2 | 2 | 0 |
| 3 | 0 | 3 |
+-------+-------------+-------------+
Removing the WHERE clause gives the total per Level but does not split it into Teams. How do I make it so both of these new columns are created and show the counts per Level?
Try the following using case expression with sum. Here is the demo.
select
level,
sum(case when team = 1 then 1 else 0 end) as Team1_count,
sum(case when team = 2 then 1 else 0 end) as Team2_count
from table
group by
level
order by
level
output
| level | Team1_count | Team2_count |
| ----- | ----------- | ----------- |
| 1 | 1 | 0 |
| 2 | 2 | 0 |
| 3 | 0 | 3 |
if you are using postgreSQL then you can use filter with count as following
select
level,
count(*) filter (where team = 1) as Team1_count,
count(*) filter (where team = 2) as Team2_count
from tableA
group by
level
order by
level

Get the number of duplicate values in separate columns

Im have table
+----+-----------+-----------+--------+
| id | peer | whom | action |
+----+-----------+-----------+--------+
| 1 | 200000001 | 213321213 | 0 |
| 2 | 200000001 | 124321213 | 1 |
| 3 | 200000001 | 124321213 | 1 |
| 4 | 200000001 | 124789123 | 1 |
+----+-----------+-----------+--------+
I need to get how many pluses and minuses the user received in total, those should result in the following table
action 0 is minus, action 1 is plus
+-----------+------+-------+
| whom | plus | minus |
+-----------+------+-------+
| 213321213 | 2 | 1 |
| 124789123 | 1 | 0 |
+-----------+------+-------+
With conditional aggregation:
select
whom,
sum(action = 1) plus,
sum(action = 0) minus
from tablename
where peer = ?
group by whom
You seem to want a simple aggregation:
select whom, sum(action) as plus, sum(1 - action) as minus
from t
group by whom;

Exclude select duplication

There is a table: prov_dl
| ID | Code | Value |
+----+----------+-------+
| 2 | PRC | 0,1701|
| 2 | Stad | 3 |
Data is stored in this form, that is,
there are several entries by code
You need to pull the data in this form:
| ID | Stadya | Percent |
+----+----------+-----------+
| 2 | 3 | 0,1701 |
I try this:
select id,
case when code='Stad' then Value end Stadya,
case when code='PRC' then Value end Percent
from prov_dl
| ID | Stadya | Percent|
+----+----------+--------+
| 2 | | 0,1701 |
| 2 | 3 | |
use max()
select id,
max(case when code='Stad' then Value end) as Stadya,
max(case when code='PRC' then Value end) as Percent
from prov_dl group by id

Oracle SQL count and group by multiple fields

I am able to get the data merging two tables to get the following table.
+------------+------+--------+--------+------------+------------+
| Group Name | Type | Manger | Status | ControlOne | ControlTwo |
+------------+------+--------+--------+------------+------------+
| Group A | 1 | 1 | finish | 2 | 2 |
| Group A | 2 | 1 | open | 0 | 2 |
| Group A | 1 | 1 | finish | 0 | 0 |
| Group A | 1 | 2 | finish | 2 | 0 |
| Group B | 1 | 1 | open | 2 | 0 |
| Group B | 1 | 2 | open | 2 | 2 |
| Group B | 2 | 2 | open | 0 | 2 |
| Group B | 2 | 1 | finish | 0 | 0 |
| Group B | 1 | 1 | open | 2 | 0 |
+------------+------+--------+--------+------------+------------+
Now I need to get the total counts based on GroupName/ Type and Manager to have the output for each group in the following format:
+------------+------+-------------------------------------------------+--------------------------------------------+------------------------------+----------------------------+
| Group Name | Type | Manager1Finish | Manager1Open | Manager2Finish | Manager2Open |
+------------+------+-------------------------------------------------+--------------------------------------------+------------------------------+----------------------------+
| Group A | 1 | 2(count of finish by Group A, manager1, type 1) | 0(count of open Manager1, Type 1, Group A) | 1(count of finish Manager 2) | 0(count of open manager 2) |
| Group A | 2 | 0 | 1 | 0 | 0 |
+------------+------+-------------------------------------------------+--------------------------------------------+------------------------------+----------------------------+
Could you please help to how to achieve this?
Try with CASE WHEN:
SELECT GroupName,
TYPE,
COUNT (CASE
WHEN Manager = 1
AND status = 'Finish'
THEN
1
END)
AS Manager1Finish,
COUNT (CASE
WHEN Manager = 1
AND status = 'Open'
THEN
1
END)
AS Manager1Open,
COUNT (CASE
WHEN Manager = 2
AND status = 'Finish'
THEN
1
END)
AS Manager2Finish,
COUNT (CASE
WHEN Manager = 2
AND status = 'Open'
THEN
2
END)
AS Manager2Open
FROM tablename
GROUP BY GroupName, TYPE
select [group], [type],
sum(case when manager=1 and status='finish' then 1 else 0 end) as m1finish,
sum(case when manager=1 and status='open' then 1 else 0 end) as m1open,
sum(...etc...)
from mytable
group by [group],[type]

SQL Aggregation depending on value of attribute in unselected column

I've got a table TABLE1 like this:
|--------------|--------------|--------------|
| POS | UNIT | VOLUME |
|--------------|--------------|--------------|
| 1 | M2 | 20 |
| 1 | M2 | 30 |
| 1 | M3 | 40 |
| 2 | M2 | 100 |
| 2 | M3 | 20 |
| 3 | ST | 30 |
| 3 | M2 | 10 |
|--------------|--------------|--------------|
Depending on the value of the column UNIT I want to aggregate as follows (each UNIT becomes a new column with the sum of the according value):
|--------------|--------------|--------------|--------------|
| POS | VOLUME_M2 | VOLUME_M3 | VOLUME_ST |
|--------------|--------------|--------------|--------------|
| 1 | 50 | 40 | 0 |
| 2 | 100 | 20 | 0 |
| 3 | 10 | 0 | 30 |
|--------------|--------------|--------------|--------------|
My Solution is
SELECT POS,
CASE
WHEN UNIT = 'M2'
THEN SUM(VOLUME)
ELSE 0
END AS VOLUME_M2,
CASE
WHEN UNIT = 'M3'
THEN SUM(VOLUME)
ELSE 0
END AS VOLUME_M3,
CASE
WHEN UNIT = 'ST'
THEN SUM(VOLUME)
ELSE 0
END AS VOLUME_S
FROM TABLE1
GROUP BY POS, UNIT
My problem is, that my code does not work if I leave out UNIT in the GROUP BY statement (I either have to use it in my aggregation or in my GROUP BY statement)
Therefore I get something like this:
|--------------|--------------|--------------|--------------|
| POS | VOLUME_M2 | VOLUME_M3 | VOLUME_ST |
|--------------|--------------|--------------|--------------|
| 1 | 50 | 0 | 0 |
| 1 | 0 | 40 | 0 |
| 2 | 0 | 20 | 0 |
| 2 | 100 | 0 | 0 |
| 3 | 10 | 0 | 0 |
| 3 | 0 | 0 | 30 |
|--------------|--------------|--------------|--------------|
Besides, could anyone give me a hint, how it is possible to automatically get this type of result (especially if there are a lot of values for UNIT).
Close. For conditional aggregation, the case expression is an argument to the aggregation function:
SELECT POS,
SUM(CASE WHEN UNIT = 'M2' THEN VOLUME ELSE 0 END) AS VOLUME_M2,
SUM(CASE WHEN UNIT = 'M3' THEN VOLUME ELSE 0 END) AS VOLUME_M3,
SUM(CASE WHEN UNIT = 'ST' THEN VOLUME ELSE 0 END) AS VOLUME_ST
FROM TABLE1
GROUP BY POS;