PHP MYSQL - select high score winner - php

Assuming we have a table like below
id | name | userid | score | date |
------------------------------------------------------------
1 | john | 1 | 44 | 2013-03-2
2 | mary | 2 | 59 | 2013-03-5
3 | john | 1 | 38 | 2013-03-8
4 | elvis | 3 | 19 | 2013-03-10
5 | john | 1 | 100 | 2013-03-11
I want to select four winner of last week.week start Sunday to Sunday.
also i want to select one winner of a month.
winner have highest score.
i use this code for weekly winner
SELECT winner.id,winner.score FROM winner WHERE winner.date >= curdate() - INTERVAL DAYOFWEEK(curdate())+6 DAY
AND winner.date < curdate() - INTERVAL DAYOFWEEK(curdate())-1 DAY ORDER BY winner.score DESC
LIMIT 4
Also monthly winner
SELECT winner.id,winner.score FROM winner WHERE MONTH(CURDATE())= MONTH(winner.date) ORDER BY winner.score DESC
LIMIT 1
both are give wrong results

Try this
select id ,score
from winner
where DATE_FORMAT(date, '%Y-%m-%d') between date_sub(DATE_FORMAT(now(), '%Y-%m-%d'),INTERVAL 1 WEEK) and DATE_FORMAT(now(), '%Y-%m-%d')
ORDER BY score DESC
LIMIT 4
-------------------
SELECT id,score FROM winner
WHERE MONTH(CURDATE())= MONTH(date)
ORDER BY score DESC
LIMIT 1
Make sure that your example data will not work because they are 2013 !!
DEMO HERE

Related

SQL - Get multiple values when limit 1

If I have a table like this:
ID | ident | product
1 | cucu1 | 99867 |
2 | kkju7 | 88987 |
3 | sjdu4 | 66754 |
4 | kjhu6 | 76654 |
5 | cucu1 | 98876 |
And use this query: SELECT ident,COUNT(*) FROM sales WHERE status=? AND team=? AND DATE(date) = DATE(NOW() - INTERVAL 1 DAY) GROUP BY ident order by COUNT(*) DESC LIMIT 1
I get the value: cucu1, since that has the most rows.
But if my table is like this:
ID | ident | product
1 | cucu1 | 99867 |
2 | kkju7 | 88987 |
3 | sjdu4 | 66754 |
4 | kkju7 | 76654 |
5 | cucu1 | 98876 |
It should return both cucu1 and kkju7, since they are the highest with same count, but still it gives me only cucu1. What am I doing wrong?
You can use rank():
SELECT ident, cnt
FROM (SELECT ident, COUNT(*) as cnt,
RANK() OVER (ORDER BY COUNT(*) DESC) as seqnum
FROM sales
WHERE status = ? AND team = ? AND
DATE(date) = DATE(NOW() - INTERVAL 1 DAY)
GROUP BY ident
) i
WHERE seqnum = 1;
LIMIT keyword simply limits the results to 1 row, no matter if there are equal values before or after the returned row.
A better solution would be to select the rows which have a count that's equal to max count in the query, which can be achieved by the following query:
SELECT ident,COUNT(*)
FROM sales
WHERE status=?
AND team=?
AND DATE(date) = DATE(NOW() - INTERVAL 1 DAY)
GROUP BY ident
HAVING COUNT(*) = MAX(COUNT(*))

Unable to fetch the accurate rooms availability in specific date range

Here is my database structure
Table name :set_inventory, and columns are below
inventory_id | room_id | quantity_start_date | quantity_end_date | total_rooms
1 | 2 | 2015-10-10 | 2015-10-12 | 5
2 | 2 | 2015-10-13 | 2015-10-14 | 10
3 | 2 | 2015-10-15 | 2015-10-17 | 0
Another Table
Table name : rooms, amd columns are
room_id | room_type | room_picture | room_description
2 | standard | pic_link | demo description
Description: In inventory table admin able to set the inventory based on multiple date ranges.
My query:
SELECT rooms.room_id, rooms.room_pic1, rooms.room_type, rooms.maximum_adults,
rooms.maximum_children, rooms.room_amenities,set_inventory.room_id,
set_inventory.quantity_start_date, set_inventory.quantity_start_date,
set_inventory.total_rooms
from rooms, set_inventory
WHERE rooms.room_id = set_inventory.room_id
AND quantity_start_date <= '2015-10-11'
AND quantity_end_date > '2015-10-13'
It shows me the inventory only 5, based in above query,
What i am looking for :actually, i am looking for the result,
for example my check_in_date "2015-10-11" and check_out_date is "2015-10-17"
In this i will be able to notify the customer that
"room is only available for 4 days,
Plz help me , thanks
UPDATED
Try this WHERE condition:
WHERE rooms.room_id = set_inventory.room_id AND DATE(quantity_start_date) <= '2015-10-11' AND DATE(quantity_end_date) > '2015-10-13';
So, minding you want to have the amount of days between these to dates, your query should contain somwthing like this:
SELECT ABS(DATEDIFF(a1.start_date, a2.end_date)) FROM (
SELECT quantity_start_date as start_date FROM set_inventory WHERE quantity_start_date <= '2015-10-11' ORDER BY start_date DESC LIMIT 1) a1, (
SELECT quantity_end_date as end_date FROM set_inventory WHERE quantity_end_date > '2015-10-13' ORDER BY end_date ASC LIMIT 1) a2;
If you try it, you'll get 4 in result.

Mixed sorting of dates in MySQL

I have a date column which holds either a date value or null. I use that to hold a product's expiration date. I want to write a query to fetch them in this order: Not yet expired, no expiration (null), and expired.
For example, assuming today is May 15:
prd_id prd_name Expiry Date
-----------------
1 name1 May 16
2 name2 May 17
3 name3 May 18
4 name4 May 21
5 namex null
6 namex null
7 namex null
8 namex May 14
9 namex May 12
(A null value denotes no expiration)
How would I do this?
You can try follwing Syntax:-
SELECT *
FROM YOUR_TABLE
ORDER BY CASE WHEN expire_date > CURDATE() THEN 1 END,
WHEN expire_date IS NULL THEN 2 Desc END,
WHEN expire_date < CURDATE() THEN 3 Desc END;
Essentially, you'll be joining three separate queries together:
SELECT * FROM (SELECT * FROM `product_entries` WHERE expires_on IS NOT NULL AND expires_on > CURDATE()
ORDER BY expires_on ASC) a
UNION ALL
SELECT * FROM (SELECT * FROM `product_entries` WHERE expires_on IS NULL) b
UNION ALL
SELECT * FROM (SELECT * FROM `product_entries` WHERE expires_on IS NOT NULL AND expires_on <= CURDATE()
ORDER BY expires_on DESC) c
The first one returns those that haven't expired, the second returns those without expiration, and the third one returns expired entries.
Keep in mind that you'd want the expires_on column to be indexed. Also, as you can see in the third query, I'm counting the current date as being expired. If you want the current day to count as not being expired, then change the <= to < in the third query, and > to >= in the first query.
Another alternative would to be to use a CASE clause (if you're not concerned about the order of each entry, so long as the non-expired are at the top, the perpetual products are in the middle, and the expired entries are at the bottom)
mysql> SELECT * FROM product_entries ORDER BY CASE
-> WHEN expires_on >= CURDATE() THEN 3
-> WHEN expires_on IS NULL THEN 2
-> WHEN expires_on < CURDATE() THEN 1
-> END DESC;
+----+-------------+
| id | expire_date |
+----+-------------+
| 9 | 2015-05-11 |
| 8 | 2015-05-06 |
| 7 | 2015-05-01 |
| 10 | NULL |
| 6 | 2015-04-26 |
| 5 | 2015-04-21 |
| 4 | 2015-04-16 |
| 3 | 2015-04-11 |
| 2 | 2015-04-06 |
| 1 | 2015-04-01 |
+----+-------------+

Counting renewals during count of subscription sold

I've a table in which write every subscription sold of my magazine, like this:
USERID | DATE |
31 | 2011-09-22 |
54 | 2011-09-22 |
59 | 2011-09-23 |
11 | 2011-10-02 |
88 | 2011-10-05 |
31 | 2011-10-06 |
17 | 2011-10-12 |
54 | 2011-10-15 |
31 | 2011-11-05 |
54 | 2011-11-12 |
Now, for statistical purpose, i need to having an outcome in which i see, for every single month, how many subscriptions i've sold and how many users have already bought once this.
For instance, if we look the datas on top, i should have an outcome likie this:
DATE | SOLD | RENEWAL
09 | 3 | 0
10 | 5 | 1
11 | 2 | 2
I can to group the subscriptions sold monthly, but i can't add the "renewal" info.
SELECT COUNT( * ) AS sold, MONTH(date) FROM table_sold WHERE date >= CURDATE() - INTERVAL 13 MONTH GROUP BY YEAR( date ) , MONTH( date ) ORDER BY date ASC LIMIT 1,15
In this way i only have an outcome like this:
DATE | SOLD
09 | 3
10 | 5
11 | 2
I've tried several option, with subquery, union and so on, but without successful.
There is to consider that the table has 70.000 entries and a query with a hard scan could be a problem.
In your opinion is there a way in mysql or i've to take the idea to make it in php?
Here is an idea. Look at the first date for each user. Then count renewals in every month that is not the first date:
select year(date), month(date), count(*) as sold,
sum(case when date <> firstdate then 1 else 0 end) as renewals
from subscriptions s join
(select userid, min(date) as firstdate
from subscriptions s
group by userid
) su
on s.userid = su.userid
group by year(date), month(date)
order by year(date), month(date);

Fetching last 30 days data from mysql table and grouping them by date

Here is how my table looks like
| total_hit |success_hit | date_time |
| 12 | 12 | 01-11-2009 07:32:44 |
| 12 | 11 | 01-11-2009 08:33:49 |
| 12 | 10 | 01-11-2009 09:08:24 |
| 12 | 11 | 01-12-2009 10:33:57 |
| 12 | 12 | 01-12-2009 11:37:34 |
| 12 | 11 | 01-12-2009 12:23:49 |
I am fetching the data from the table for the past 30 days using the following query:
SELECT *
FROM my_table
WHERE DATE(date_time) >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)
what I want to do is group the returned data in terms of date and calculate the percentage success (success_hit/total_hit)*100
Something like
Date: 01-11-2009 Percentage: x
Date: 01-12-2009 Percentage: y
any ideas?
select (success/total)*100 as perc_success, Date(date_time) from
(select sum(success_hit) as success, sum(total_hit) as total,
date_time from my_table
where DATE(date_time) >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)
group by Date(date_time) )
tbl
This should work!!!
Try this
SELECT (sum(success_hit)/sum(total_hit)*100) AS `Percentage`,
DATE(date_time) AS `Date`
FROM my_table
WHERE DATE(date_time) >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)
GROUP BY DATE(date_time);

Categories