SQL Renaming NULL for null values and rollup - sql

I'm trying to make a dashboard to show open tickets and who they are assigned to, by priority. The data set looks like:
|-------------------------|
| Assigned | Priority |
|-------------------------|
| JOE | Low |
| JOE | Medium |
| MARY | High |
| | Medium |
| TIM | Low |
| Mary | High |
The report I'm trying to get is:
|---------------------------------------------------------|
| Employee | Low | Medium | High | Total |
|---------------------------------------------------------|
| Total | 2 | 2 | 2 | 6 |
| Unassigned | 0 | 1 | 0 | 1 |
| MARY | 0 | 0 | 2 | 2 |
| JOE | 1 | 1 | 0 | 2 |
| TIM | 1 | 0 | 0 | 1 |
I can get it all, with this query
SELECT
CASE WHEN Assigned is null then 'Unassigned' Else Assigned End Employee
, SUM(CASE WHEN Priority = 'Low' THEN 1 ELSE 0 END) AS Low
, SUM(CASE WHEN Priority = 'Medium' THEN 1 ELSE 0 END) AS Medium
, SUM(CASE WHEN Priority = 'High' THEN 1 ELSE 0 END) AS High
, count(Priority) AS Total
FROM table
GROUP BY Assigned WITH ROLLUP
ORDER BY Assigned ASC
This way however, it is renaming anything that was NULL to Unassigned. This is perfect to give me the Unassigned values that don't have anyone in the Assigned field, however my Total column is also showing Unassigned. How do I rename that to Total?
Thanks in advance!

You need to use GROUPING, like this:
SQL Fiddle
SELECT
CASE WHEN (GROUPING(Assigned) = 1) THEN 'Total'
When Assigned is null then 'Unassigned'
Else Assigned End Employee
, SUM(CASE WHEN Priority = 'Low' THEN 1 ELSE 0 END) AS Low
, SUM(CASE WHEN Priority = 'Medium' THEN 1 ELSE 0 END) AS Medium
, SUM(CASE WHEN Priority = 'High' THEN 1 ELSE 0 END) AS High
, count(Priority) AS Total
FROM table1
GROUP BY Assigned WITH ROLLUP
--DER BY Assigned ASC
Results:
| EMPLOYEE | LOW | MEDIUM | HIGH | TOTAL |
|------------|-----|--------|------|-------|
| Unassigned | 0 | 1 | 0 | 1 |
| JOE | 1 | 1 | 0 | 2 |
| MARY | 0 | 0 | 2 | 2 |
| TIM | 1 | 0 | 0 | 1 |
| Total | 2 | 2 | 2 | 6 |

Related

Combining fields with GROUP BY ROLLUP

I want to have a query that shows every contract made in my company and have it grouped by function.
My problem is that I have a lot of functions, for instance:
Partner
Seller
Manager
Captain
Etc.
I want to show 3 rows, one with all contracts from "Partners", other by all the "Interns" (everyone that isn't a partner), and last one with a Total of the two, achieved with the ROLLUP. But I can't seem to only show this 3 rows, my query turns everything that is not partner to be name "intern", but doesn't combine this cells, so I get this result:
+--------------+-------------+--------------+---------+
| Seller Type | Installed | Scheduled | Total |
+--------------+-------------+--------------+---------+
| Intern | 1 | 0 | 1 |
+--------------+-------------+--------------+---------+
| Intern | 3 | 0 | 3 |
+--------------+-------------+--------------+---------+
| Partner | 10 | 5 | 15 |
+--------------+-------------+--------------+---------+
| Intern | 19 | 10 | 29 |
+--------------+-------------+--------------+---------+
| Total | 33 | 15 | 48 |
+--------------+-------------+--------------+---------+
And my goal was to Group everyone that isn't a "partner" into the same row, and show it like this:
+--------------+-------------+--------------+---------+
| Seller Type | Installed | Scheduled | Total |
+--------------+-------------+--------------+---------+
| Partner | 10 | 5 | 15 |
+--------------+-------------+--------------+---------+
| Intern | 23 | 10 | 33 |
+--------------+-------------+--------------+---------+
| Total | 33 | 15 | 48 |
+--------------+-------------+--------------+---------+
My data for table CM3
+--------------+-------------+--------------+
| u_func | cm | name |
+--------------+-------------+--------------+
| Captain | 1 | Chris |
+--------------+-------------+--------------+
| Manager | 2 | Mary |
+--------------+-------------+--------------+
| Partner | 3 | Anthony |
+--------------+-------------+--------------+
| Seller | 4 | Hannah |
+--------------+-------------+--------------+
My data for table BO
+--------------+-------------+--------------+
| stamp | seller | sta |
+--------------+-------------+--------------+
| PO109832910 | 1 | Installed |
+--------------+-------------+--------------+
| PO389213201 | 2 | Installed |
+--------------+-------------+--------------+
| PO930821639 | 3 | Scheduled |
+--------------+-------------+--------------+
| PO987583213 | 4 | Scheduled |
+--------------+-------------+--------------+
My query is
SELECT CASE
WHEN GROUPING(CM3.u_func)=1 THEN 'TOTAL'
WHEN CM3.u_func <> 'Partner' THEN 'Intern'
END "Seller Type"
, COUNT(CASE
WHEN BO.stat = 'Installed' THEN 1
END) "Installed"
, COUNT(CASE
WHEN BO.stat = 'Scheduled' THEN 1
END) "Scheduled"
, COUNT(CASE
WHEN BO.stat IN ('Installed','Scheduled') THEN 1
END) "Total"
FROM BO
JOIN CM3 ON cm3.cm = BO.seller
GROUP BY ROLLUP(CM3.u_func)
You need your GROUP BY to mirror the logic in your SELECT statement (which also needs some adjustment):
SELECT CASE
WHEN GROUPING
(CASE
WHEN CM3.u_func = 'Partner' THEN CM3.u_func
ELSE 'Intern'
END) = 1 THEN 'TOTAL'
ELSE CASE
WHEN CM3.u_func = 'Partner' THEN CM3.u_func
ELSE 'Intern'
END
END "Seller Type"
, COUNT(CASE
WHEN BO.stat = 'Installed' THEN 1
END) "Installed"
, COUNT(CASE
WHEN BO.stat = 'Scheduled' THEN 1
END) "Scheduled"
, COUNT(CASE
WHEN BO.stat IN ('Installed','Scheduled') THEN 1
END) "Total"
FROM BO
JOIN CM3 ON cm3.cm = BO.seller
GROUP BY CASE
WHEN CM3.u_func = 'Partner' THEN CM3.u_func ELSE 'Intern'
END WITH ROLLUP

Presto SQL - Trying to pull data from multiple columns into one entry to find a unique, missing, or dupe entry

new to SQL/Presto here.
Feel free to point out the obvious if needed.
I have a sub query that pulls data into a table like below.
For each ItemID, 1 would mean that the tag is on, 0 is off.
I am trying to make a query that would pull up each ItemID with its associated tag if its unique, otherwise point out if there is more than one or if its missing.
Data_Table
| ItemID | TagA | TagB | TagC | TagD | TagE |
| 111 | 1 | 1 | 0 | 0 | 0 |
| 222 | 1 | 1 | 1 | 0 | 0 |
| 333 | 1 | 1 | 0 | 0 | 0 |
| 444 | 0 | 1 | 0 | 0 | 0 |
| 555 | 0 | 0 | 0 | 0 | 0 |
| 666 | 0 | 0 | 0 | 1 | 1 |
I tried a case when statement that pull each 1 and another case query that tries to convert each column into just one row entry.
SELECT Item_ID,
CASE WHEN (Tag_A+Tag_B+Tag_C+Tag_D+Tag_E > 1) THEN 'Dupe'
ELSE (CASE WHEN Tag_A = 1 THEN 'TagA_Present'
WHEN Tag_B = 1 THEN 'TagB_Present'
WHEN Tag_C = 1 THEN 'TagC_Present'
WHEN Tag_D = 1 THEN 'TagD_Present'
WHEN Tag_E = 1 THEN 'TagE_Present'
ELSE 'Missing_Tag' END)
END as ItemTag
FROM Data_Table
EDITED - I went too far with the sample data and initial query has been changed.
Actual Results
| ItemID | ItemTag |
| 111 | Dupe |
| 222 | TagA_Present |
| 333 | TagB_Present |
| 444 | TagB_Present |
| 555 | Missing |
| 666 | TagD_Present |
ItemID 111, 222, 333, and 666 should all be 'Dupe', but the results seems to be deeming random ones unique.
Hmmm. I am thinking:
select t.itemId,
(case when (TagA + TagB + TagC + TagD + TagE) > 1 then 'Dupe'
when TagA = 1 then 'TagA'
when TagB = 1 then 'TagB'
when TagC = 1 then 'TagC'
when TagD = 1 then 'TagD'
when TagE = 1 then 'TagE'
else 'Missing'
end) as ItemTag
from Data_Table;
There is no reason to use aggregation for this.

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 Server Pivot table for survey responses

I have a sql server table called surveys with the following data
+------------+--------------+----+----+----+----+
| ModuleCode | SurveyNumber | Q1 | Q2 | Q3 | Q4 |
+------------+--------------+----+----+----+----+
| NME3519 | 1 | 5 | 4 | 5 | 3 |
| NME3519 | 2 | 3 | 3 | 2 | 1 |
| NME3519 | 3 | 4 | 3 | 2 | 1 |
| NME3520 | 1 | 4 | 3 | 2 | 1 |
| NME3519 | 4 | 4 | 2 | 2 | 1 |
+------------+--------------+----+----+----+----+
I'd like to be able to report on one module at a time and for the result to be something like this:
Count of scores
+----------+---+---+---+---+---+
| Question | 1 | 2 | 3 | 4 | 5 |
+----------+---+---+---+---+---+
| Q1 | 0 | 0 | 1 | 2 | 1 |
| Q2 | 0 | 1 | 2 | 1 | 0 |
| Q3 | 0 | 3 | 0 | 0 | 1 |
| Q4 | 3 | 0 | 1 | 0 | 0 |
+----------+---+---+---+---+---+
I'm pretty sure from other examples I need to unpivot and then pivot but I can't get anywhere with my own data.
Many thanks
Richard
Unpivot and aggregate:
select v.question,
sum(case when v.score = 1 then 1 else 0 end) as score_1,
sum(case when v.score = 2 then 1 else 0 end) as score_2,
sum(case when v.score = 3 then 1 else 0 end) as score_3,
sum(case when v.score = 4 then 1 else 0 end) as score_4,
sum(case when v.score = 5 then 1 else 0 end) as score_5
from responses r cross apply
( values ('Q1', r.q1), ('Q2', r.q2), ('Q3', r.q3), ('Q4', r.q4), ('Q5', r.q5)
) v(question, score)
group by v.question;
This version uses a lateral join for unpivoting. I find the syntax simpler and lateral joins more powerful. Why bother learning unpivot when something else does the same thing more concisely, more powerfully, and has the same performance?
As for the pivoting, it uses conditional aggregation. In my experience with SQL Server, this has pretty much the same performance as pivot.

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;