TSQL Join Query with count - tsql

I have 2 tables I am joining to get some stats for a tool. I need to combine both of them to be able to get a count on the number of results that both tables will hold.
Below is the structure.
Table A
Account, tag
123, dog
456, cat,
123, pig
456, mouse
333, dog
Table B
tag, totalSearches
dog, 10
cat, 2
pig, 4
mouse, 4
Expected Result
Tag, Total Accounts Tag is On, Total Times Searched
dog, 2 , 10
cat, 1, 2
pig, 1, 4
mouse, 1, 4
I am just a little unsure on how to join the tables while also getting the count on the numbers of results that it finds.

You can have result using this SQL:
SELECT
TA.TAG AS Tag,
COUNT(TA.Account) AS TotalAccountsTagIsOn,
MAX(TB.totalSearches) AS TotalTimesSearched
FROM
TableA AS TA
INNER JOIN TableB AS TB ON
(TA.Tag = TB.Tag)
GROUP BY
TA.TAG;
You JOIN (connect) Table A and Table B using Tag column. You then GROUP BY Tag.
And COUNT Accounts and MAX totalSearches, because you have more than 1 row for each Tag in Table A.

Related

Agreggating multiple category columns in postgreSQL

I have this table in my postgreSQL db that I need to aggregate in categories.
The table called "table1" looks like this
Column A
Column B
Column C
Apple
Volks
200
Apple
Volks
350
Lime
BMW
200
Apple
BMW
200
Lime
BMW
400
I want the output to look like this:
Column A
Column B
Column C
Apple
Volks
550
Apple
BMW
200
Lime
BMW
600
I've tried using groupby and sum(Column C) but it didn't worked out.
SELECT distinct Column A, Column B, sum(Column C) as "Sum of C"
GROUP BY Column A, Column B, Column C
FROM public.table1
You should not be aggregating and grouping the same column, and distinct is irrelevant given a group by already results in distinct groups; your syntax is also wrong, that query would result in an error as From must precede Group By.
However you can use distinct in an aggregation, like so:
SELECT Column_A, Column_B, sum(distinct Column_C) as "Sum of C"
FROM public.table1
GROUP BY Column_A, Column_B;

PostgreSQL: Merging sets of rows which text fields are contained in other sets of rows

Given the following table, I need to merge the fields in different "id" only if they are the same type (person or dog), and always as the value of every field of an "id" is contained in the values of other "ids".
id
being
feature
values
1
person
name
John;Paul
1
person
surname
Smith
2
dog
name
Ringo
3
dog
name
Snowy
4
person
name
John
4
person
surname
5
person
name
John;Ringo
5
person
surname
Smith
In this example, the merge results should be as follows:
1 and 4 (Since 4's name is present in 1's name and 4's surname is empty)
1 and 5 cannot be merged (the name field show different values)
4 and 5 can be merged
2 and 3 (dogs) cannot be merged. They have only the field "name" and they do not share values.
2 and 3 cannot be merged with 1, 4, 5 since they have different values in "being".
id
being
feature
values
1
person
name
John;Paul
1
person
surname
Smith
2
dog
name
Ringo
3
dog
name
Snowy
5
person
name
John;Ringo
5
person
surname
Smith
I have tried this:
UPDATE table a
SET values = (SELECT array_to_string(array_agg(distinct values),';') AS values FROM table b
WHERE a.being= b.being
AND a.feature= b.feature
AND a.id<> b.id
AND a.values LIKE '%'||a.values||'%'
)
WHERE (select count (*) FROM (SELECT DISTINCT c.being, c.id from table c where a.being=c.being) as temp) >1
;
This doesn't work well because it will merge, for example, 1 and 5. Besides, it duplicates values when merging that field.
One option is to aggregate names with surnames on "id" and "being". Once you get a single string per "id", a self join may find when a full name is completely included inside another (where the "being" is same for both "id"s), then you just select the smallest fullname, candidate for deletion:
WITH cte AS (
SELECT id,
being,
STRING_AGG(values, ';') AS fullname
FROM tab
GROUP BY id,
being
)
DELETE FROM tab
WHERE id IN (SELECT t2.id
FROM cte t1
INNER JOIN cte t2
ON t1.being = t2.being
AND t1.id > t2.id
AND t1.fullname LIKE CONCAT('%',t2.fullname,'%'));
Check the demo here.

How to join two tables in PostgreSQL with similar columns and leave unmatching fields NULL or untouched

I have a main table Grade. I already joined this table with the Class table. Now I want to join another table, Instructor.
Grade
ClassID
AverageGrade
1
A
2
B
3
B+
Class
ID
Class
1
Math
2
English
3
History
4
Spanish
5
Science
Instructor
Class
Instructor
1
Alice
2
Bob
4
Charlie
The current query I have is
select * from Grade left join Class on Grade.ClassID = Class.ID
Is there any way I can left join Instructor on top of this query, such that my table has the following?
ID
Class
AverageGrade
Instructor
1
Math
A
Alice
2
English
B
Bob
3
History
B+
4
Spanish
Charlie
Not including 5-Science as it has neither a grade nor an instructor.
Due to other reasons, I have to join Grade first.
Thanks!
No, you can not LEFT JOIN Instructor on top of the query you have, because the first table (Grade) limits the amount of records you get in result when using left joins. You can't have NULL from Grade table in result if you are only left join'ing.
Other options:
Having to start from Grade limits some most obvious options, but I still can think of two:
Using right join to join class and then joining instructor. This way I need to filter out classes without instructors and grades in WHERE part:
select
Class.ID,
Class.Class,
Grade.AverageGrade,
Instructor.Instructor
from
Grade
right join Class on Grade.ClassID = Class.ID
left join Instructor on Class.ID = Instructor.Class
where
Grade.AverageGrade is not null
or instructor.Instructor is not null
Using full join of grade and instructor returns the records I need, so no filtering is needed later, but the class should be joined using id from either grade or instructor as one of them may be NULL.
select
Class.ID,
Class.Class,
Grade.AverageGrade,
Instructor.Instructor
from
Grade
full join Instructor on Grade.ClassID = Instructor.Class
join Class on coalesce(Grade.ClassID, Instructor.class) = Class.ID
They both return the same result.

hive 1.1 take out hierarchy value from three tables

I have the following tables in HIVE (1.1 version) and need the output as shown in the Result. As UNION is not available in hive 1.1, need different approach to get the below result.
Table A:
id name
1 One
2 Two
4 Four
Table B:
id name
1 ONE
3 THREE
4 FOUR
Table C:
id name
1 one
2 two
3 three
5 five
Result
id name
1 One
2 Two
3 THREE
4 Four
5 five
select id, name from A
UNION ALL
SELECT sec.id, sec.name FROM B sec WHERE sec.id NOT IN (SELECT id FROM A)
UNION ALL
SELECT thr.id, thr.name FROM c thr WHERE thr.id NOT IN (SELECT id FROM A UNION ALL SELECT id FROM B)

SSRS 2005 column chart: show series label missing when data count is zero

I have a pretty simple chart with a likely common issue. I've searched for several hours on the interweb but only get so far in finding a similar situation.
the basics of what I'm pulling contains a created_by, person_id and risk score
the risk score can be:
1 VERY LOW
2 LOW
3 MODERATE STABLE
4 MODERATE AT RISK
5 HIGH
6 VERY HIGH
I want to get a headcount of persons at each risk score and display a risk count even if there is a count of 0 for that risk score but SSRS 2005 likes to suppress zero counts.
I've tried this in the point labels
=IIF(IsNothing(count(Fields!person_id.value)),0,count(Fields!person_id.value))
Ex: I'm missing values for "1 LOW" as the creator does not have any "1 LOW" they've assigned risk scores for.
*here's a screenshot of what I get but I'd like to have a column even for a count when it still doesn't exist in the returned results.
#Nathan
Example scenario:
select professor.name, grades.score, student.person_id
from student
inner join grades on student.person_id = grades.person_id
inner join professor on student.professor_id = professor.professor_id
where
student.professor_id = #professor
Not all students are necessarily in the grades table.
I have a =Count(Fields!person_id.Value) for my data points & series is grouped on =Fields!score.Value
If there were a bunch of A,B,D grades but no C & F's how would I show labels for potentially non-existent counts
In your example, the problem is that no results are returned for grades that are not linked to any students. To solve this ideally there would be a table in your source system which listed all the possible values of "score" (e.g. A - F) and you would join this into your query such that at least one row was returned for each possible value.
If such a table doesn't exist and the possible score values are known and static, then you could manually create a list of them in your query. In the example below I create a subquery that returns a combination of all professors and all possible scores (A - F) and then LEFT join this to the grades and students tables (left join means that the professor/score rows will be returned even if no students have those scores in the "grades" table).
SELECT
professor.name
, professorgrades.score
, student.person_id
FROM
(
SELECT professor_id, score
FROM professor
CROSS JOIN
(
SELECT 'A' AS score
UNION
SELECT 'B'
UNION
SELECT 'C'
UNION
SELECT 'D'
UNION
SELECT 'E'
UNION
SELECT 'F'
) availablegrades
) professorgrades
INNER JOIN professor ON professorgrades.professor_id = professor.professor_id
LEFT JOIN grades ON professorgrades.score = grades.score
LEFT JOIN student ON grades.person_id = student.person_id AND
professorgrades.professor_id = student.professor_id
WHERE professorgrades.professor_id = 1
See a live example of how this works here: SQLFIDDLE
SELECT RS.RiskScoreId, RS.Description, SUM(DT.RiskCount) AS RiskCount
FROM (
SELECT RiskScoreId, 1 AS RiskCount
FROM People
UNION ALL
SELECT RiskScoreId, 0 AS RiskCount
FROM RiskScores
) DT
INNER JOIN RiskScores RS ON RS.RiskScoreId = DT.RiskScoreId
GROUP BY RS.RiskScoreId, RS.Description
ORDER BY RS.RiskScoreId