Create a top 3 leader table with tie'd scores - sql-server-2008

I'm currently trying to do a leader board based on 4 metrics, i kept it simple doing Select TOP (3) from my table ordering by largest to smallest. Then added in a ROW_NUMBER() to give the 1, 2, 3. Then aggregating it up i created a case when to assign 100 to No1, 50 to No2 and 25 to No3.
Issue I've got is I get a tie for some of the scores. it then uses the next field to sort and drops one down to 50 points when I want joint to both have 100. Hope i've explained this OK?
I'm sure there's a smarter way of doing this?

Related

MySQL query for an MLB database

There are 5 tables: mlb_batting, mlb_manager, mlb_master, mlb_pitching, mlb_team.
Find the top 10 (highest) “strike outs per walk” statistic for all pitches with at least 1 walk that played in at least 25 games. You should display their first name, last name, and K/BB statistic. K/BB is computed by dividing the number of strike outs by the number of walks (“base on balls”). You will need to use “limit” in MySQL (not talked about in class or notes – you will have to search how to do it). I would like this query done 2 different ways. One that only looks at the 25 games and 1 walk on a per stint basis. That is, if they played for two different teams (two different stints) then you would count those separate. And the other query should combine all the stints they had. That is, if they played for two different teams you would add up their games and walks.
My solution is:
SELECT NAME_FIRST, NAME_LAST, SUM(strikeouts) / SUM(walks) AS KS_PER_BB
FROM mlb_master
JOIN mlb_pitching
ON mlb_master.player_id = mlb_pitching.player_id
WHERE walks >= 1 AND games >= 25
GROUP BY name_first, name_last, mlb_pitching.stint
ORDER BY KS_PER_BB DESC
LIMIT 10;
I am wondering if this solution is better for the first way my professor wants it done or the second way, if any.
This solution is appropriate for the first query because by having GROUP BY stint, each stint is considered different for each player.
For the second way, could I remove the stint column from the GROUP BY clause so that it groups the records for a particular player together, regardless of the different stints they played for?
Would this result in the sum of all their walks and strikeouts from all their stints being used to calculate the KS_PER_BB statistic, giving you the combined total for each player?

How to design a MySQL database for storing sell items

I have been trying to design a MySQL table o store the items of the store purchased by the costumers. I am stuck with what approach should I take to design a good table.
My first option is:
id
bill_id_fk
item1_id
item2_id
item3_id
item4_id
In this approach, I'll create may be 20 columns for items (assuming that a costumer may buy a maximum of 20 items at a time). ID of the items will be stored in the item(n)_id columns for that specific bill_id_fk.
My concern with this approach is that it would be difficult to query later for a specific item, like how many times a specific item has been sold.
My second opinion is:
id
bill_id_fk
item_id
1
1
23
2
1
29
3
2
23
In this approach, I'll just create 3 columns and for each item I'll create a rows with the bill_id_fk for a specific bill.
In this approach, it is easier to query for a counts of the sell of a specific item. But my concern is creating thousands and thousands of rows when the app will be used and how will that affect the performance of the app over time?
I'd like to have your opinion on what is the best practice for designing such database. Or is there any other approach should I take?
There's no chance that you will go with the first choice, the second is the best approach for your case.
it will not affect your performance if you indexed the right columns.
When it comes to items can add a column to your bills table that holds item numbers, for example:
bills (id - total_price - user_id - item_counts)
bill_items (id - bill_id - item_id - item_price)

how to compute percentage in mysql/sql when 2 group by conditions are present

id title count organizer
1 music 4 2
2 sports 6 2
3 music 2 3
I have a derived table with the above structure. I need to compute the percentage of the number of events of each organizer for each title. i.e. I'm expecting a result like:
organizer title percentage
2 music 40%
2 sports 60%
3 music 100%
The way I'm doing it without organizer in consideration produces the percentage aggregating all the values easily but introducing organizer messes it all up. Can anyone help me here??
Taking your derived table as the actual data (may not be optimal) you could:
select to.organizer, to.title, 100.0*to.count/o.count as percentage
from
(select organizer, sum(count) as count from derivedtable group by organizer) o
inner join
derivedtable to
on
to.organizer = o.organizer
It works by summing the data per organizer to get a total, and joining this back to the data you have so you can do the particular event-organizer count divided by the total count for that organiser
There might have been a simpler way to do it with your source data, as is you'll have to plug your query in that creates your derived table, possibly making it messy. Probably simplest to do as a CTE, but do try to include original source data and "query so far" next time you ask a question, otherwise we have to build a solution on top of some solution we know nothing about and the result might not be optimal
You can try below - using scalar subquery
DEMO
select organizer,title,count*100/(select sum(count) from tablename b where a.organizer=b.organizer)
from tablename a
OUTPUT:
organizer title percentage
2 music 40.0000
2 sports 60.0000
3 music 100.0000

Query to get number of records where 0, using 2 tables

Table Structure
Table structure brief
We have 2 tables Weight and Weight_Sub, they are both identical. Our users weigh-in every 2 days and every team have a captain. So after each weigh-in team captain adds the weight according to the date in the Weight_Sub table and for that we add records in Weight table with weight 0. Once the team player accepts that score we delete them from Weight_Sub and update scores in main table i.e. Weight. E.g. If a player on 01/03/2015 was weighed 98KG we'll add there record in Weight_Sub= 98 and in Weight= 0. Once player will accept that weight then we will delete that row from Weight_Sub table and update weight in Weight table from 0 to 98.
I hope it makes sense.
Problem
We want to make a check when player accepts the score that did he missed any weigh-in. Like in the above table for 03/03/2015 in both tables the weight is 0,0 that means player missed a weigh-in. We want to get those missed weigh-in dates. The thing is we only want missed weigh-in dates which were missed after accepting the last weight, in this case on 07/03/2015.
So if you see the above image, player missed weigh-in on the 03/03/2015 but on 07/03/2015 he accepted the weight as 100KG. After that he missed 3 consecutive weighin's and then accepted on the 15/03/2015. So the query should return 3 dates i.e. 09/03/2015, 11/03/2015, 13/03/2015.
I know it can be done using PHP by running the loop and breaking when I find the accpted scores and get dates for missed weighin's but I'm looking for something for more efficient if there is.
This query will return missed records before a given date.
select w1.ID, w1.Date, w1.Weight
from `WeightTable` w1
where w1.Date < '07/03/2015' and w1.Weight = 0

"Sparse" Rank in Business Objects XI Web Intelligence?

In Business Objects XI Web Intelligence the Rank function returns dense results. For example when ranking by "Amount" I want to return the top ten records only. However three records tie for 5th place on "Amount". Result is a total of 12 records: one each for places 1 to 4 and 6 to 10 and 3 records for 5th place.
Desired result is a "sparse" top ten that drops the two lowest ranked records (places 9 and 10).
I tried to do this and rank customers by amount.
I have 2 objects: [Amount] and [Customernumber].
[Customernumber] is numeric.
I created a new variable:
[varForSorting]=[Amount]*10000000+ToNumber([Customernumber])
Then I rank by the new variable [varForSorting].
Customers with the same Amount will be sorted in Alphabetic order by Customer number. I hope this helps.
Here is an example of how I solved it for a change in Account Count over time. This approach allows you to break your dense rank ties using other measures in your data provider. Basically you use multiple measures in one rank and decide which measure to rank by first, second, etc:
Step 1: Determine the change amount
v_Account_Count_Delta_Amount
=([v_Account_Count_After] - [v_Account_Count_Before])
Step 2: Rank the change amounts (this is where ties and dense rank cause multiple rows to be returned)
v_Account_Count_Delta_Amount_Rank
=NoFilter(Rank([v_Account_Count_Delta_Amount]))
Step 3: Compute the tie breaking rank using other measures
v_MonthToDateMeasuresRank
=NoFilter(Rank([Month To Date Sva]+ [Bank Share Balance] + [Total Commitment]))
Step 4: Compute a combined rank that is now free from ties and weight your ranks however you choose
v_Account_Count_Combined_Rank
=Rank([v_Account_Count_Delta_Amount_Rank]* 1000000 + [v_MonthToDateMeasuresRank];Bottom)
Step 5: Filter your data block for v_Account_Count_Combined_Rank <= 10
Ultimately depending on your data it could still result in a tie unless you take the additional step of ranking by some other unique attribute that you can turn to a number (see Maria Ruchko's answer for that bit of magic using Customer Number). I tried to do that with RowIndex() and LineNumber() but could not get usable results. My measures when added together happen to never tie so this works for my specific data blob.