sum in mysql than group by - mysql

I am making a small lottery game for fun and to improve myself.
On the database, I have
table(id, package, value, price, purchase_code,round)
See an example. There is two package, package1 and package2.
package1 has a value of 3 and package2 has a value of 4. This means, that if I buy the package1, i got 3 ticket which is playing, giving me bigger chance to win in the current round, so it inserts 3 record into a table, containing the informations. So in this case, I have the following records in my table:
id pacakage_id value price purchase_code round
1 1 3 10 w3hjkrw 1
2 1 3 10 w3hjkrw 1
3 1 3 10 w3hjkrw 1
I would like to see overall how money the users spent , and for this, I used sum(price).
Ok, but as you can see, the three record was one purchase, so sum(price) would give me the result 30. I tried to group by purchase_code, but it is not doing what I want.
Here is the code:
$income_query = mysql_query("SELECT SUM(price) FROM lottery WHERE round = '$current_round' GROUP BY code") or die(mysql_error());
while($result = mysql_fetch_array($income_query)) {
$round_money = $result['SUM(price)']." $";

Think you will need to do a sub query to get the package id price. Possibly using distinct, although I would just use a normal aggregate function (MAX will do the job here).
Something like this:-
SELECT code, SUM(package_id_price)
FROM(
SELECT code, package_id, MAX(price) AS package_id_price
FROM lottery
WHERE round = '$current_round'
GROUP BY code, package_id
) Sub1
GROUP BY code

Related

SQL: Find closest number to given value with ties

I'm trying to find the closest number(s) to a given value in SQL. I have already made my query for multiple results:
SELECT *
FROM Cars
ORDER BY ABS(price - $price)
I know I can limit the table by using LIMIT 1, by which I have one number closest to the given value. But how can I include ties? Like for example when there are three or four cars with the same price? The amount of cars which have the same price is dynamic, so I can't specify a certain LIMIT.
I also know I could use SELECT TOP 1 WITH TIES, but I can't use this query because my database driver doesn't allow it. Does anybody have another idea of how to accomplish this?
Example:
car 1 = 2000
car 2 = 3000
car 3 = 3000
car 4 = 1500
When I want the cars closest to 3000, the query should return:
car 2
car 3
But without using a static LIMIT in the query, because the amount of cars with the same price can be different every time. Thanks
If your driver supports nested queries:
SELECT *
FROM CARS
WHERE ABS(price - $price) = ( SELECT MIN(ABS(price - $price)) FROM CARS )

Need Help building a SQL query

I was wondering if anyone could help me with this, I have had a go at a number of things like using union queries but I think I am looking in the wrong place.
I am trying to run a SQL query on a singular table to provide to users with only datareader permissions to discover total sales.
The table itself contains sales and refunds which have a type of 1 or 3 in the database.
Table example structure:
Reference TransactionType StockCode Value
Sale01 1 Bat1 10
Sale01 1 Bat1 10
Sale09 1 Ball1 3
Sale15 1 Shin1 50
Sale16 1 Bat1 10
Refund06 3 Bat1 10
What I need to get is a total value for stock whereby the refund total is taken away from the total sum so that it appears as such:
StockCode TotalSales
Bat1 20
Ball1 3
Shin1 50
This means that I would have to have a calcuation under one column that says:
Select (if type is 1 then sum(value) - (if type is 3 then sum(value)
In honestly I simply can't do it! I have tried using temporary tables and such but it has completely stumped me.
Here you go
SELECT StockCode,
SUM( (CASE WHEN TransactionType = 3 THEN -1 ELSE 1 END) * Value)
FROM yourtable
GROUP BY StockCode

Triple count and groupby using MySql on a simple table... is it possible in one query?

I'm having a question that can be explained using a simple fictive table.
Table "Drinks" has just three fields:
Id (1..N) - Primary key
Date ('2012-09-19'...) - Each date can occur very often
Hot (1 for yes, and 0 for false).
I would like to produce a list like this:
Date Total Hot Cold
2012-09-19 14 6 8
2012-09-10 21 18 3
Etc.
The field "Cold" is as you might expect calculated as (Total - Hot).
What I've got so far is:
SELECT Date, count(*) AS Total FROM Drinks GROUP BY Date;
This gives me the desired table, but of course without the columns "Hot" and "Cold".
Is there a way to modify my query so I can produce this table in one go? I can of course built the table in phases using PHP code, but that is probably not the elegant way nor the fastest.
I'm happy to watch and learn... :)
You can add CASE statements in your SELECT clause.
SELECT Date,
count(*) AS Total,
SUM(CASE WHEN Hot = 1 THEN 1 ELSE 0 END) totlHOT,
SUM(CASE WHEN Hot = 0 THEN 1 ELSE 0 END) totalCold
FROM Drinks
GROUP BY Date;
SELECT Date,
count(*) AS Total,
SUM(Hot = 1) Hot,
SUM(Hot = 0) Cold
FROM Drinks
GROUP BY Date;

Selecting most recent as part of group by (or other solution ...)

I've got a table where the columns that matter look like this:
username
source
description
My goal is to get the 10 most recent records where a user/source combination is unique. From the following data:
1 katie facebook loved it!
2 katie facebook it could have been better.
3 tom twitter less then 140
4 katie twitter Wowzers!
The query should return records 2,3 and 4 (assume higher IDs are more recent - the actual table uses a timestamp column).
My current solution 'works' but requires 1 select to generate the 10 records, then 1 select to get the proper description per row (so 11 selects to generate 10 records) ... I have to imagine there's a better way to go. That solution is:
SELECT max(id) as MAX_ID, username, source, topic
FROM events
GROUP BY source, username
ORDER BY MAX_ID desc;
It returns the proper ids, but the wrong descriptions so I can then select the proper descriptions by the record ID.
Untested, but you should be able to handle this with a join:
SELECT
fullEvent.id,
fullEvent.username,
fullEvent.source,
fullEvent.topic
FROM
events fullEvent JOIN
(
SELECT max(id) as MAX_ID, username, source
FROM events
GROUP BY source, username
) maxEvent ON maxEvent.MAX_ID = fullEvent.id
ORDER BY fullEvent.id desc;

How would I do this in MySQL?

Lets say I have a database of widgets. I am showing a list of the top ten groupings of each widget, separated by category.
So lets say I want to show a list of all widgets in category A, but I want to sort them based on the total number of widgets in that category and only show the top 10 groupings.
So, my list might look something like this.
Top groupings in Category A
100 Widgets made by company 1 in 1990.
90 Widgets made by company 1 in 1993.
70 Widgets made by company 3 in 1993.
etc...(for 10 groupings)
This part is easy, but now lets say I want a certain grouping to ALWAYS show up in the listings even if it doesnt actually make the top ten.
Lets say I ALWAYS want to show the number of Widgets made by company 1 in 2009, but I want this grouping to be shown somewhere in my list randomly (not first or last)
So the end list should look something like
Top groupings in Category A
100 Widgets made by company 1 in 1990.
90 Widgets made by company 1 in 1993.
30 Widgets made by company 1 in 2009.
70 Widgets made by company 3 in 1993.
How would i accomplish this in MySQL?
thanks
Edit:
Currently, my query looks like this
SELECT
year,
manufacturer,
MAX(price) AS price,
image_url,
COUNT(id) AS total
FROM
widgets
WHERE
category_id = A
AND
year <> ''
AND
manufacturer <> ''
GROUP BY
category_id,
manufacturer,
year
ORDER BY
total DESC,
price ASC
LIMIT
10
);
Thats without the mandatory grouping in there.
The placement doesnt necessarily have to be random, just shouldnt be on any extreme end. And the list should be 10 groupings including the mandatory listing. So 9 + 1
I would use an UNION query: your current query union the query for 2009, then handle the sorting in the presentation layer.
You can write 2 separate query (one for all companies and another just for company 1) and then use UNION to join them together. Finally, add ORDER BY RAND().
It will look like
SELECT * FROM
(
SELECT company_id, company_name, year, count(*) as num_widgets
....
LIMIT 10
UNION DISTINCT
SELECT company_id, company_name, year, count(*) as num_widgets
...
WHERE company_id =1
...
LIMIT 10
)x
ORDER BY RAND();
You could add a field that you make true for company 1 in 2009 and include it in the where clause. Something like
select * from companies where group = 'some group' or included = true order by included, widgets_made limit 10
For the random part you would have that as subquery then include a column that has a random number from 1 to 10 if the field that you made is true, and rownum otherwise, then sort by that column