How do I output rating of teams? [closed] - sql

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I have 2 tables: team(team_id, name), performance(team_id, stage, place, date). Teams should earn points: for 1st place - 10 points, for 2nd 5, for 3rd - 3 points and 1 point for 4-7 places. I need to output the rating of teams.
I think it should be like:
SELECT team.name, CASE place
WHEN 1 points + 10
WHEN 2 points + 5
...
Expected reasult:
|---------------------|------------------|
| team.name | Points |
|---------------------|------------------|
| Rockers | 34 |
|---------------------|------------------|
| Batmans | 23 |
|---------------------|------------------|
| ... | ... |
|---------------------|------------------|

First aggregate inside the table performance to calculate the total points of each team with conditional aggregation and then join the table team to the results and rank the teams with RANK() or maybe DENSE_RANK() analytical functions:
select t.team_id, t.name,
coalesce(p.points, 0) points,
rank() over (order by coalesce(p.points, 0) desc) rnk
from team t left join (
select team_id,
sum(
case
when place = 1 then 10
when place = 2 then 5
when place = 3 then 3
when place <= 7 then 1
else 0
end
) points
from performance
group by team_id
) p on p.team_id = t.team_id

Related

How to split a group by query? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 months ago.
Improve this question
I have a table like this:
Id 1
Id 2
Amount
001
AAA
10
001
AAA
10
001
AAA
10
001
AAA
10
001
AAA
10
001
AAA
10
001
AAA
10
001
AAA
10
001
AAA
10
001
AAA
10
If I do a select query like
SELECT id1,id2,sum(amount),count(*) from table group by id1,id2;
I get the answer like;
001 |AAA |100 |10
What I want to do is split this into two aggregates, so that the first 8 rows will have one aggregate sum and the next 2 should have the sum of next two rows [8 is the cut off].
For example, the answer should be like:
001 |AAA |80 |8
001 |AAA |20 |2
Is it possible to achieve this?
As mentioned in comments, the order of 8 rows+2 rows doesn't matter just that the records in both batches be mutually exclusive. Thanks #SadlyFullStack for the answer!
Since order doesn't matter, we can use ceil and row_number with a null order clause in a CTE to flag every 8 rows with a number. Then, we have another query to aggregate those based on the group number we created:
with grouped as
(
select tbl.*
, ceil(row_number() over (order by null) / 8) grp_num
from tbl
)
select id1
, id2
, sum(amount)
, count(*)
from grouped
group by id1, id2, grp_num

How can I count number of appearance of a value and make it into a new column when querying? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I have a table like this
ProductID | SalesOrderNumber
1 | SO0001
2 | SO0002
3 | SO0001
4 | SO0001
5 | SO0002
I want to query the table into this
ProductID | SalesOrderNumber | SalesOrderLineNumber
1 | SO0001 | 1
2 | SO0002 | 1
3 | SO0001 | 2
4 | SO0001 | 3
5 | SO0002 | 2
Basically, the SalesOrderLineNumber will count the number of time SalesOrderNumber appear. Everytime a same value of SalesOrderNumber show up, SalesOrderLineNumber increase.
How can I do it?
You should use:
SELECT ProductID,
SalesOrderNumber,
ROW_NUMBER() OVER (PARTITION BY SalesOrderNumber ORDER BY ProductId) as SalesOrderLineNumber
FROM yourTable;
The difference between this and the other answer is the use of ProductId in the ORDER BY clause. You seem to want the line numbers ordered by product id, so this seems to capture the intention.
More importantly: If the order has no duplicate products, then this always produces the same results -- that is, the results are stable. If you repeat the partitioning key, then you could get different results each time you run the query.
You can use a window function, ROW_NUMBER(), for this:
SELECT
ProductID,
SalesOrderNumber,
ROW_NUMBER() OVER (PARTITION BY SalesOrderNumber ORDER BY SalesOrderNumber) as SalesOrderLineNumber
FROM yourTable
The ROW_NUMBER() will count the number of times SalesOrderNumber occurs, as we partition by that.

How to compute overlap percentage of agreement between people in Hive table

Suppose I have a survey where each question has 4 possible answers, and surveyed people can choose at least one answer (multiple answers allowed). I want to compute per question per answer, how many people chose that answer. For example, if I have the hive table:
question_id | answer_id | person_id
-------------------------------------
1 | A | 1
1 | B | 1
1 | C | 1
1 | D | 1
1 | A | 2
1 | B | 2
1 | C | 2
2 | D | 1
2 | A | 1
Then the resulting table would be:
question_id | answer_id | Percentage
-------------------------------------
1 | A | 100
1 | B | 100
1 | C | 100
1 | D | 50
2 | D | 50
2 | A | 50
For question 1, both people put A,B,C giving 100% for all three, but one person put D as well, giving 50%. For question 2, one person put D and one person put A, giving 50% and 50%.
I've been really stuck and I haven't been able to find anything online that accomplishes what I'm looking for. Any help would be amazing!
Hmmm . . . If I understand correctly, you want the number of people who chose one particular question/answer combination divided by the people who chose the question. If so, I think
select qa.*, qa.num_persons * 100.0 / q.num_persons
from (select question_id, answer_id, count(*) as num_persons
from t
group by question_id, answer_id
) qa join
(select question_id, count(distinct person_id) as num_persons
from t
group by question_id
) q
on qa.question_id = q.question_id;
Also you can use analytic functions and size(collect_set) for counting distinct. This will allow to eliminate join and will work fine if the number of distinct person per question is not too big (array produced by collect_set can fit in memory)
select qa.question_id, qa.answer_id,
qa.num_persons * 100.0 / size(qa.question_persons) as Percentage
from (select question_id, answer_id,
count(*) over (partition by question_id, answer_id) as num_persons,
collect_set(person_id) over(partition by question_id) as question_persons
from t
) qa;
I'm not familiar with prestoDB but below is a SQL script that will have the same result as what you posted.
The 2.0 is the number of person. You might want to select that first and store it in a vairable.
select
question_id, answer_id, (count(answer_id)/2.0) * 100.0
from Sample
group by question_id, answer_id
order by question_Id, answer_id

Database Design question best way to solve this issue [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I'm kind of new in database design and I'm trying to find the best way to solve an issue I'm facing.
Let's think about the following example:
Imagine I want to store information about patients and these patients can have 0+ diseases.
What's the best way of storing arranging the tables to display the diseases that each patient can have? I get confused as to what happens when a patient would have 3 diseases; how is this stored in a relational database? e.g. without having repeated rows on the diseases table for example (static number of diseases)..
I'm not sure if I'm making myself totally clear here!
But let's say I don't think it's efficient to have:
Patient table -
Patient_id , disease_id
1, (3,4,5,6)
Any help is appreciated!
As mentioned in the comments, you would use an associative entity for that.
Let say you have the following diseases:
| Disease_id | Disease_name |
-----------------------------
| 1 | Cancer |
-----------------------------
| 2 | Leucemia |
-----------------------------
Your patients may look like this
| Patient_id | Patient_name |
-----------------------------
| 1 | Peter Jones |
-----------------------------
| 2 | Mark Jacobs |
-----------------------------
You now create a table like so (lets call it ill_patients)
| Patient_id | Disease_id |
---------------------------
| 1 | 1 |
---------------------------
| 1 | 2 |
---------------------------
This would mean that poor Peter Jones has cancer as well as leucemia. You can now query your patient table like so:
SELECT patients.patient_name, diseases.disease_name
FROM (diseases INNER JOIN ill_patients ON diseases.disease_id = ill_patients.disease_id) INNER JOIN patients ON ill_patients.patient_id = patients.patient_id;
This gives you all the patients with their respective diseaes.
Patients:
patient_id, name, phone
Disease:
disease_id, name, description
Patient_Disease:
patient_id, disease_id
Example:
patient_id, name , phone
1 , 'jhon', '555-1234'
disease_id, name , description
1 , 'Cancer' , 'Cancer is the uncontrolled development of cells.'
2 , 'Diabetes', 'Diabetes is a disease that occurs when your blood glucose is too high.'
patient_id, disease_id
1 , 1
1 , 2
Then you can do
SELECT p.name, d.name, d.description
FROM patients p
JOIN patient_disease pd
ON p.patient_id = pd.patient_id
JOIN diseases d
ON pd.disease_id = d.disease_id

sql query get Data on pre conditions [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
i need fruit list which price greater than in tableA for each fruit.
ID | fruit | Price
----------------------------
1 | apple | 10
2 | banana| 7
3 | grapes| 6
then i have daily table like below
ID | fruit | Price
----------------------------
1 | apple | 9
2 | banana| 5
3 | grapes| 9
4 | mango | 15
in this condition i get only grapes
I think you can just join the daily and tableA tables on the fruit's ID, and then compare prices.
SELECT t1.*
FROM daily t1
INNER JOIN tableA t2
ON t1.ID = t2.ID
WHERE t1.price > t2.price
Note that we join on the ID rather than the fruit name, since in theory names may not be completely unique across a very large table of fruits.
just join by ID and add your additional condition (price in tableA is greater than price in dailyTable).
you don't need to join by column fruit - but if so, it won't change your resultset.
SELECT TableA.*, dailyTable.Price
FROM TableA
INNER JOIN dailyTable
ON TableA.ID = dailyTable.ID
AND TableA.Price > dailyTable.Price
the column fruit is redundant data. so you shouldn't store it in the daily table.