Conditional Group in SSRS Tablix or DB View - tsql

I've created a report that is supposed to use a tablix to group data exactly as seen below:
Region | State | Customer | CustomerKey | Status
North | NY | Bob | 111 | VIP
| | Mary | 112 | VIP
| MA | Bob | 111 | Regular
| | Tim | 113 | Regular
East | MD | Greg | 114 | VIP
| VA | Bob | 111 | VIP
West | CA | Greg | 114 | Regular
| | Mary | 112 | VIP
| | Sean | 115 | Regular
| WA | Sean | 115 | VIP
This is relatively easy because I am using a view with all the appropriate fields and relations to make grouping in the tablix simple. I only run into a problem with my VIP Customers.
In the view, customers who have VIP status also have duplicate records of them with Regular status. For example, the data is stored as follows:
Region | State | Customer | CustomerKey | Status
North | NY | Bob | 111 | VIP
North | NY | Bob | 111 | Regular
North | NY | Mary | 112 | VIP
North | NY | Mary | 112 | Regular
North | MA | Bob | 111 | Regular
North | MA | Tim | 113 | Regular
East | MD | Greg | 114 | VIP
East | MD | Greg | 114 | Regular
East | VA | Bob | 111 | VIP
East | VA | Bob | 111 | Regular
West | CA | Greg | 114 | Regular
West | CA | Mary | 112 | VIP
West | CA | Mary | 112 | Regular
West | CA | Sean | 115 | Regular
West | WA | Sean | 115 | VIP
West | WA | Sean | 115 | Regular
My SSRS report is therefore displaying the data as follows:
Region | State | Customer | CustomerKey | Status
North | NY | Bob | 111 | VIP
| | | | Regular
| | Mary | 112 | VIP
| | | | Regular
| MA | Bob | 111 | Regular
| | Tim | 113 | Regular
East | MD | Greg | 114 | VIP
| | | | Regular
| VA | Bob | 111 | VIP
| | | | Regular
West | CA | Greg | 114 | Regular
| | Mary | 112 | VIP
| | | | Regular
| | Sean | 115 | Regular
| WA | Sean | 115 | VIP
| | | | Regular
If a user has a Status of VIP, I don't care about their record with their Status of Regular (for that particular Region/State). Is there anyway I can hide these conditionally? Thanks in advance

Personally I'd look at solving this at a database query level in the first instance.
That said, one way at the report level would be to set up Groups based on Region, State and Customer, then in the Status column you could have an expression like:
=IIf(CountRows("CustomerGroup") = 2, "VIP", "Regular")
It's a bit clunky, but should work as it seems each customer can either have one or two rows at the Region/State level - if two they must be VIP, and since you've set a a group you're getting distinct values for Customers within each Region/State combo.

Related

R, Group By in Subquery

I was practicing on some subqueries and I got stuck on a problem. This is for the table below (snippet). The question is "From the following tables, write a SQL query to find those employees whose salaries exceed 50% of their department's total salary bill. Return first name, last name."
My query is this below, but it does not run. I ran the subquery by itself, and it ran fine. I think it's something to do with the GROUP BY in the subquery.
SELECT first_name, last_name
FROM employees
WHERE salary >
(
SELECT (sum(salary)) / 2
FROM employees
GROUP BY department_id
)
The correct answer from the practice is below. Is creating table e2 necessary?
SELECT e1.first_name, e1.last_name
FROM employees e1
WHERE salary >
( SELECT (SUM(salary))*.5
FROM employees e2
WHERE e1.department_id=e2.department_id);
+-------------+-------------+-------------+----------+--------------------+------------+------------+----------+----------------+------------+---------------+
| EMPLOYEE_ID | FIRST_NAME | LAST_NAME | EMAIL | PHONE_NUMBER | HIRE_DATE | JOB_ID | SALARY | COMMISSION_PCT | MANAGER_ID | DEPARTMENT_ID |
+-------------+-------------+-------------+----------+--------------------+------------+------------+----------+----------------+------------+---------------+
| 100 | Steven | King | SKING | 515.123.4567 | 2003-06-17 | AD_PRES | 24000.00 | 0.00 | 0 | 90 |
| 101 | Neena | Kochhar | NKOCHHAR | 515.123.4568 | 2005-09-21 | AD_VP | 17000.00 | 0.00 | 100 | 90 |
| 102 | Lex | De Haan | LDEHAAN | 515.123.4569 | 2001-01-13 | AD_VP | 17000.00 | 0.00 | 100 | 90 |
| 103 | Alexander | Hunold | AHUNOLD | 590.423.4567 | 2006-01-03 | IT_PROG | 9000.00 | 0.00 | 102 | 60 |
| 104 | Bruce | Ernst | BERNST | 590.423.4568 | 2007-05-21 | IT_PROG | 6000.00 | 0.00 | 103 | 60 |
| 105 | David | Austin | DAUSTIN | 590.423.4569 | 2005-06-25 | IT_PROG | 4800.00 | 0.00 | 103 | 60 |
| 106 | Valli | Pataballa | VPATABAL | 590.423.4560 | 2006-02-05 | IT_PROG | 4800.00 | 0.00 | 103 | 60 |
| 107 | Diana | Lorentz | DLORENTZ | 590.423.5567 | 2007-02-07 | IT_PROG | 4200.00 | 0.00 | 103 | 60 |
| 108 | Nancy | Greenberg | NGREENBE | 515.124.4569 | 2002-08-17 | FI_MGR | 12008.00 | 0.00 | 101 | 100 |
| 109 | Daniel | Faviet | DFAVIET | 515.124.4169 | 2002-08-16 | FI_ACCOUNT | 9000.00 | 0.00 | 108 | 100 |
| 110 | John | Chen | JCHEN | 515.124.4269 | 2005-09-28 | FI_ACCOUNT | 8200.00 | 0.00 | 108 | 100
SELECT first_name, last_name
FROM employees
WHERE salary >
(
SELECT (sum(salary)) / 2
FROM employees
GROUP BY department_id
)
I expected this to run, but it did not execute. The editor on the website I'm practicing from does not give error info.

PostgreSQL Need rows to return even if the result is 0

I know this has been asked a bit on here and I have tried several of the answers with no progress. My goal is to be able to also see which Tracking Numbers had 0 calls during the date range.
I have tried several joins, sub-queries, and way to much time. Any help would be greatly appreciated.
SELECT org_unit_name "Group Name",
call_detail.ring_to_name "Ad Source(s)",
tracking "Tracking Number",
COUNT(call.call_id)"Calls",
SUM(bill_second)/60 "Total Duration (Sec)"
FROM CALL
JOIN call_detail ON call.call_id = call_detail.call_id
JOIN org_unit o ON call.org_unit_id = o.org_unit_id
WHERE billing_id = 3104
AND call_started BETWEEN '2020-01-01' AND '2020-01-31'
GROUP BY 1,2,3
Here is a sample of how the data is coming back:
| Group Name | Ad Source(s) | Tracking Number | Calls | Total Duration (Sec) |
|--------------------------|------------------------------|-----------------|-------|----------------------|
| Westin Riverfront Villas | Desert Willow Explorer | 8883926768 | 2 | 9 |
| Sheraton Maui | Postcard-Owner | 8885322865 | 36 | 82 |
| Westin Maui | CS On-Site Pre Arrival calls | 8885939052 | 35 | 128 |
| Sheraton Kauai | Email Renter | 8887248492 | 24 | 91 |
But I need 6th and 8th line to show up as well even/especially since they have had no calls.
Westin Princeville and Westin Nanea Resort had no calls but should be on the report
| Group Name | Ad Source(s) | Tracking Number | Calls | Total Duration (Sec) |
|--------------------------|---------------------------------|-----------------|-------|----------------------|
| Westin Maui | CS On-Site Pre Arrival calls | 8885939052 | 35 | 128 |
| Westin Riverfront Villas | Desert Willow Explorer | 8883926768 | 2 | 9 |
| Sheraton Kauai | Email Renter | 8887248492 | 24 | 91 |
| Westin Princeville | In-House pre-arrival phone call | 8776921840 | 0 | 0 |
| Sheraton Maui | Postcard-Owner | 8885322865 | 36 | 82 |
| Westin Nanea Resort | Pre-Arrival E-Mail Nanea WVP | 8887218839 | 0 | 0 |

I need help identifying group of table members that have different status in another table

I wasn't able to google my way to figuring this out. I'm still very new to TSQL and I thought I could solve this with a self joins and sub queries. But I'm getting to many results and don't know how to tame them. I appreciate the help. It's nice to see all the different methods people suggest for the same problem. I know I get tunnel vision when trying to solve a problem, when it's better to try it from a different angle.
My goal is this. I want to Return the HouseholdID of all Households whose PersonID's HairColor don't all match each other. Whatever the color may be. So below HouseHoldID 200 would return since their PersonID's HairColor differ from each other. Unlike HouseHoldID 300 whose PersonID's HairColor do match each other.
HouseholdMember
+------------+-----------------+-----------+
| MemberID | HouseholdID | PersonID |
+------------+-----------------+-----------+
| 100 | 200 | 1 |
| 101 | 200 | 2 |
| 102 | 200 | 3 |
| 103 | 300 | 4 |
| 104 | 300 | 5 |
| 105 | 300 | 6 |
+------------+-----------------+-----------+
Person
+------------+-----------------+-----------+------------+
| PersonID | FirstName | LastName | HairColor |
+------------+-----------------+-----------+------------+
| 1 | Josh | Smith | Brown |
| 2 | Jerry | Smith | Black |
| 3 | Ethan | Smith | Red |
| 4 | Mike | Jones | Black |
| 5 | Devan | Jones | Black |
| 6 | Todd | Jones | Black |
+------------+-----------------+-----------+------------+
Household
+---------------+-----------------+----------------+
| HouseholdID | Name | Address |
+---------------+-----------------+----------------+
| 200 | Smith's | 123 Candy Dr |
| 300 | Jones's | 812 Dentist Ln |
+---------------+-----------------+----------------+
One option uses aggregation:
WITH cte AS (
SELECT hm.HouseholdID
FROM HouseholdMember hm
INNER JOIN Person p ON hm.PersonID = p.PersonID
GROUP BY hm.HouseholdID
HAVING COUNT(DISTINCT p.HairColor) > 1
)
SELECT *
FROM Household
WHERE HouseholdID IN (SELECT HouseholdID FROM cte);
Demo

Create Calculated Pivot from Several Query Results in PostgreSQL

I have question regarding how to make a calculated pivot table from several query results on PostgreSQL. I've managed to make three queries results but don't have any idea how to combine and calculate all the data into a single table. I've tried to google it but found out that most of the question is about how to make a pivot table from a single table, which I'm able to do using sum, case, and group by. Well, Here's the simplified version of my query results
Query from query 1 which contains gross value
| city | code | gross |
|-------|------|--------|
| city1 | 21 | 194793 |
| city1 | 25 | 139241 |
| city1 | 28 | 231365 |
| city2 | 21 | 282025 |
| city2 | 25 | 334458 |
| city2 | 28 | 410852 |
| city3 | 21 | 109237 |
Result from query 2 which contains positive adjustments
| city | code | adj_pos |
|-------|------|---------|
| city1 | 21 | 16259 |
| city1 | 25 | 13634 |
| city1 | 28 | 45854 |
| city2 | 25 | 18060 |
| city2 | 28 | 18220 |
Result from query 3 which contains negative adjustments
| city | code | adj_neg |
|-------|------|---------|
| city1 | 25 | 23364 |
| city2 | 21 | 27478 |
| city2 | 25 | 23474 |
And what I want to to is to create something like this
| city | 21_gross | 25_gross | 28_gross | 21_pos | 25_pos | 28_pos | 21_neg | 25_neg | 28_neg |
|-------|----------|----------|----------|--------|--------|--------|--------|--------|--------|
| city1 | 194793 | 139241 | 231365 | 16259 | 13634 | 45854 | | 23364 | |
| city2 | 282025 | 334458 | 410852 | | 18060 | 18220 | 27478 | 23474 | |
| city3 | 109237 | | | | | | | | |
or probably final calculation which come from gross + positive adjustment -
negative adjustment from each city on each code like this
| city | 21_nett | 25_nett | 28_nett |
|-------|---------|---------|---------|
| city1 | 211052 | 129511 | 277219 |
| city2 | 254547 | 329044 | 429072 |
| city3 | 109237 | 0 | 0 |
Any suggestion will be appreciated. Thank you!
I think the best you can achieve is to get the pivoting part as JSON - http://sqlfiddle.com/#!17/b7d64/23:
select
city,
json_object_agg(
code,
coalesce(gross,0) + coalesce(adj_pos,0) - coalesce(adj_neg,0)
) as js
from q1
left join q2 using (city,code)
left join q3 using (city,code)
group by city

How can I combine two similar columns in Tableau?

I am using Tableau Public to read data from a '|' separated text file. The goal is to determine how much damage each player dealt versus received. Currently the data only shows rows for each attacker. How can I change the data so that I see a row for each player?
Sample Source:
Attacker Name | Attacker Nation | Defender Name | Defender Nation | Attacking Damage | Defending Damage
Bob | Builder | Felix | Fixer | 100 | 120
Bob | Builder | Ralph | Wrecker | 150 | 75
Felix | Fixer | Ralph | Wrecker | 125 | 150
Desired Output:
Name | Nation | Opponent Name | Opponent Nation | Damage Dealt | Damage Received
Bob | Builder | Felix | Fixer | 100 | 120
Bob | Builder | Ralph | Wrecker | 150 | 75
Felix | Fixer | Bob | Builder | 120 | 100
Felix | Fixer | Ralph | Wrecker | 125 | 150
Ralph | Wrecker | Bob | Builder | 75 | 150
Ralph | Wrecker | Felix | Fixer | 150 | 125