Having Groups based on distinct count of another column - sql

I have a table as follow :
+-------------+-----------+------+
| GroupNumber | TeamName | Goal |
+-------------+-----------+------+
| 1 | Sales | ABC |
| 1 | Sales | ABC |
| 1 | Sales | ABC |
| 1 | Design | XYZ |
| 2 | Design | XYZ |
| 2 | Sales | XYZ |
| 2 | technical | XYZ |
| 2 | Support | XYZ |
| 3 | Sales | XYZ |
| 3 | Sales | XYZ |
| 3 | Sales | XYZ |
+-------------+-----------+------+
I want to output only the groups that have unique teams greater than 3.
Only group 2 has this condition so the output is :
Expected Output:
+-------------+-----------+------+
| GroupNumber | TeamName | Goal |
+-------------+-----------+------+
| 2 | Design | XYZ |
| 2 | Sales | XYZ |
| 2 | technical | XYZ |
| 2 | Support | XYZ |
+-------------+-----------+------+
not sure how to utilize this in subquery
SELECT count(Distinct(TeamName))
FROM mytable
group by [GroupNumber]
HAVING COUNT(Distinct[TeamName])>3

Simply put it in a Subquery:
select *
from mytable
where [GroupNumber] in
(
SELECT [GroupNumber]
FROM mytable
group by [GroupNumber]
HAVING COUNT(Distinct[TeamName])>3
)

Please try
SELECT *
FROM mytable where GroupNumber in (select GroupNumber
FROM mytable group by TeamName
HAVING COUNT(TeamName)>3)

Related

Summarize count of multi table in single SQL query

I have three table with below details:
Table 1: worklog
+-----------+------------+-------------+
| worklogid | technician | description |
+-----------+------------+-------------+
| 1 | john | some text |
+-----------+------------+-------------+
| 2 | jack | some text |
+-----------+------------+-------------+
| 3 | john | some text |
+-----------+------------+-------------+
| 4 | jenifer | some text |
+-----------+------------+-------------+
Table 2: task
+--------+-------+-------------+
| taskid | owner | description |
+--------+-------+-------------+
| 1 | john | some text |
+--------+-------+-------------+
| 2 | john | some text |
+--------+-------+-------------+
| 3 | john | some text |
+--------+-------+-------------+
| 4 | jack | some text |
+--------+-------+-------------+
Table 3: request
+-----------+------------+-----------+-------------+
| requestid | technician | title | description |
+-----------+------------+-----------+-------------+
| 1 | john | some text | ... |
+-----------+------------+-----------+-------------+
| 2 | sara | some text | ... |
+-----------+------------+-----------+-------------+
| 3 | john | some text | ... |
+-----------+------------+-----------+-------------+
| 4 | jack | some text | ... |
+-----------+------------+-----------+-------------+
Now I need to SQL query for this result:
+------------+------------------+---------------+------------------+
| technician | count(worklogid) | count(taskid) | count(requestid) |
+------------+------------------+---------------+------------------+
| john | 2 | 3 | 2 |
+------------+------------------+---------------+------------------+
| jack | 1 | 1 | 1 |
+------------+------------------+---------------+------------------+
| jenifer | 1 | 0 | 0 |
+------------+------------------+---------------+------------------+
| sara | 0 | 0 | 1 |
+------------+------------------+---------------+------------------+
What should I do?
One method is to just use union all and aggregation:
select techician, sum(is_workid), sum(is_taskid), sum(is_requestid)
from ((select technician, 1 as is_workid, 0 as is_taskid, 0 as is_requestid
from worklog
) union all
(select owner, 0, 1, 0
from task
) union all
(select technician, 0, 0, 1
from request
)
) t
group by technician;
In Postgres, you can also aggregate before joining:
select *
from (select technician, count(*) as num_workid
from worklog
group by technician
) w full join
(select owner as technician, count(*) as num_task
from task
group by owner
) t
using (technician) full join
(select technician, count(*) as num_request
from request
group by technician
) w
using (technician);
With a full join, I find that using is simpler than on clauses. But the name needs to be the same in all the tables.

SQL calculating sum and number of distinct values within group

I want to calculate
(1) total sales amount
(2) number of distinct stores per product
in one query, if possible. Suppose we have data:
+-----------+---------+-------+--------+
| store | product | month | amount |
+-----------+---------+-------+--------+
| Anthill | A | 1 | 1 |
| Anthill | A | 2 | 1 |
| Anthill | A | 3 | 1 |
| Beetle | A | 1 | 1 |
| Beetle | A | 3 | 1 |
| Cockroach | A | 1 | 1 |
| Cockroach | A | 2 | 1 |
| Cockroach | A | 3 | 1 |
| Anthill | B | 1 | 1 |
| Beetle | B | 2 | 1 |
| Cockroach | B | 3 | 1 |
+-----------+---------+-------+--------+
I have tried this with no luck:
select
[product]
,[month]
,[amount]
,cnt_distinct_stores = count(distinct(stores))
from dbo.temp
group by
[product]
,[month]
order by 1,2
Would there be possible any combination of GROUP BY clause with window functions like SUM(amount) OVER(partition by [product],[month] ORDER BY [month] ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
Try
SELECT product,
SUM(amount),
COUNT(DISTINCT store)
FROM dbo.temp
GROUP BY product

sort a table while keeping the hierarchy of rows

I have a table which represents the hierarchy of departments:
+-----------+--------------+--------------+--------------+-----------+-------+
| Top Dept. | 2-tier Dept. | 3-tire Dept. | 4-tier Dept. | name | tier |
+-----------+--------------+--------------+--------------+-----------+-------+
| 00 | | | | abc | 0 |
| | 00-01 | | | bcd | 1 |
| | | 00-01-01 | | cde | 2 |
| | | 00-01-02 | | abc | 2 |
| | 00-02 | | | aef | 1 |
| | | 00-02-01 | | qwe | 2 |
| | | 00-02-03 | | abc | 2 |
| | | | 00-02-03-01 | abc | 3 |
+-----------+--------------+--------------+--------------+-----------+-------+
now I want to sort the rows which are in the same tier by their names while keeping the hierarchy overall, That's what I expect:
+-----------+--------------+--------------+--------------+-----------+-------+
| Top Dept. | 2-tier Dept. | 3-tire Dept. | 4-tier Dept. | name | tier |
+-----------+--------------+--------------+--------------+-----------+-------+
| 00 | | | | abc | 0 |
| | 00-02 | | | aef | 1 |
| | | 00-02-03 | | abc | 2 |
| | | 00-02-01 | | qwe | 2 |
| | 00-01 | | | def | 1 |
| | | 00-01-02 | | abc | 2 |
| | | 00-01-01 | | cde | 2 |
| | | | 00-02-03-01 | abc | 3 |
+-----------+--------------+--------------+--------------+-----------+-------+
the missing data means null, I'm using Oracle DB, can anyone help me?
EDIT: Actually, it's a simple version of this sql, I've tried to add a new column which concats the values of the first four columns and then order by it and by name, but it did't work.
Update: This appears to be working... SQL Fiddle
All that was really needed from my original comment was to amend name to department in that order in both selects. This allows the engine to sort by name first, while maintaining the hierarchy.
WITH cte(Dept, superiorDept, name, depth, sort)AS (
SELECT
Dept,
superiorDept,
name,
0,
name|| dept
FROM hierarchy h
WHERE superiorDept IS NULL
UNION ALL
SELECT
h2.Dept,
h2.superiorDept,
h2.name,
cte.depth + 1,
cte.sort || h2.name ||h2.dept
FROM hierarchy h2
INNER JOIN cte ON h2.superiorDept = cte.Dept
)
SELECT
CASE WHEN depth = 0 THEN Dept END AS 一级部门,
CASE WHEN depth = 1 THEN Dept END AS 二级部门,
CASE WHEN depth = 2 THEN Dept END AS 三级部门,
CASE WHEN depth = 3 THEN Dept END AS 四级部门,
name,
depth,
sort
FROM cte
ORDER BY sort, name

count distinct value of field on every row

table: item_tbl
|item_id |serial_code|item_name|
------------------------------
| 1 | x35 | bullet |
| 2 | 6ox | cord |
| 3 | 0hg | cord |
| 4 | a73 | tv |
| 5 | lo5 | bullet |
I tried to use SELECT serial_code, item_name, COUNT(item_name) FROM item_tbl but not what i expected of course. How can I count the distinct values of item_name to have something like:
|serial_code|item_name| count |
-----------------------------
| x35 | bullet | 2 |
| 6ox | cord | 2 |
| 0hg | cord | 2 |
| a73 | tv | 1 |
| lo5 | bullet | 2 |
SELECT Serial_Code, count.Item_Name, Count
FROM
item_tbl i
INNER JOIN
(
SELECT Item_Name, COUNT(1) Count
FROM item_tbl
GROUP BY item_Name
) count ON i.item_Name = count.Item_Name
Lets see if that works.

SQL Query in MANY- MANY RELATIONSHIP exactly one record with matching criteria

I have 3 like with many - many relationship
As:
TABLE 1 : select * from student;
| id | name |
| 1 | sone |
| 2 | stwo |
| 3 | sthree |
| 4 | sfour |
| 6 | ssix |
TABLE 2 : select * from course;
| id | name |
| 100 | CSE |
| 101 | ECE |
| 102 | ITI |
RELATION_SHIP TABLE : select * from student_course
| id | stu_id | cou_id |
| 1 | 1 | 101 |
| 2 | 2 | 102 |
| 3 | 2 | 100 |
| 4 | 3 | 100 |
| 5 | 3 | 101 |
| 6 | 1 | 101 |
| 1 | 6 | 101 |
I need to write a query to select a student with exactly one course 'CSE' and he should not have any other courses.
Thanks in advance
Use query:
SELECT
sc.`stu_id`,
COUNT(sc.`cou_id`) AS cnt
FROM
student_course sc
GROUP BY sc.`stu_id`
HAVING cnt = 1
AND GROUP_CONCAT(cou_id) LIKE
(SELECT
id
FROM
course
WHERE NAME = 'CSE')